7

Avec les pages ASP.NET MVC normales, le référentiel est transmis au constructeur du contrôle. Ensuite, les tests peuvent instancier le contrôleur passant dans un faux référentiel. Comment puis-je faire cela avec les services Web? Le problème que je vois est que nous n'avons pas l'équivalent de ControllerBuilder.SetControllerFactory. Quelles sont les meilleures pratiques pour que mon infrastructure IoC (Castle) instancie mon service Web avec l'implémentation correcte du référentiel?Comment utiliser l'injection de dépendance et le modèle de référentiel avec les services Web ASP.NET?

Je pensais qu'il pourrait y avoir un moyen d'étendre HttpHandler et de changer la façon dont le service Web est réellement instancié. Je crois que c'est ainsi que le cadre MVC le fait.

+0

Quelle technologie utilisez-vous pour mettre en œuvre vos services Web? Services Web ASP.NET ou Windows Communication Foundation? –

+0

Services Web ASP.NET. Cependant, après avoir lu la réponse de jrista, je pense que cela pourrait valoir la peine de se pencher sur WCF si je veux vraiment injecter des dépendances. Je considère juste avoir deux constructeurs - un qui prend le référentiel en tant que paramètres (les tests appelleront celui-ci) et un par défaut qui dur codera: ceci (nouvel IRepository) et sera appelé par le cadre ASP.NET. –

Répondre

1

Je crois que vous êtes à la recherche de la MFA intégration du château de Windsor. Il fournit une implémentation ServiceHost qui prend en charge le processus de construction de vos implémentations de service, en utilisant le CIO de Windsor.Vous pouvez injecter des dépendances comme toute autre application IoC utilisant cette installation, et assez commodément, sa partie du projet Château:

http://www.castleproject.org/container/facilities/trunk/wcf/index.html

Si la version du projet Castle ne fait pas ce que vous avez besoin de faire, je mon propre établissement que j'ai créé pour faire la même chose pour Windsor avant de trouver la version du projet Castle. Ils font tous les deux généralement la même chose, mais les deux abordent aussi le problème un peu différemment.

+0

Je suppose que la réponse est "vous ne pouvez pas utiliser l'injection de constructeur avec les services web ASP.NET", donc utilisez BuildUp (this) ou utilisez WCF avec castle. –

+1

En fait, vous devriez pouvoir utiliser Castle Windsor avec des services de style ASMX (si c'est ce que vous voulez dire). Je pensais que vous posiez des questions sur la WCF, mais je ne vois pas pourquoi vous ne pourriez pas intégrer Windsor dans le pipeline ASMX également. Ce n'est probablement pas aussi facile qu'avec la WCF, mais cela ne devrait pas être impossible. – jrista

+0

@jrista étant donné que ServiceHost n'est pas autorisé dans le fichier asmx, avez-vous un exemple d'implémentation de DI pour les services asmx? – Nobody

2

Ceci est une bonne question. J'ai le même problème. Je pense que si vous créez des services Web en utilisant des fichiers .asmx, il est impossible d'utiliser l'injection de constructeur. Si vous utilisiez WCF pour implémenter le service web à la place, alors je pense que c'est possible.

Dans mon service Web .asmx, je laisse le conteneur DI définir les dépendances en définissant les propriétés. Comme mon application est aussi une application web asp.net, je ne peux pas non plus utiliser l'injection de constructeur sur des formulaires web. Mais j'utilise StructureMap, et il a une fonction BuildUp qui peut définir les propriétés d'un objet déjà créé. Pas aussi propre que l'injection constructeur, mais un bon compromis. Mais les services Web se différencient des formulaires Web, car je peux placer l'accumulation en dehors du formulaire Web, dans l'événement Application_PostMapRequestHandler. Mais je n'ai pas découvert un événement qui est déclenché après la création de la classe de service Web. Ainsi, dans le constructeur de mon service Web, j'ai le code suivant

ObjectFactory.BuildUp(this); 

Et c'est un anti-pattern. Une classe initialisée par un conteneur DI ne doit pas connaître le conteneur DI lui-même. Mais je n'ai pas encore trouvé une meilleure solution.

0

Définissez une classe de base et utilisez l'injection de propriété dans cette classe. Pete l'a déjà dit, mais vous feriez: ObjectFactory.BuildUp (this); La différence est que je le mettrais sur une classe de base pour les services web, donc c'est "automatique" pour les implémentations spécifiques.

De cette façon, c'est une ligne, donc je m'en fous, sauf si vous avez le besoin explicite de changer de conteneurs DI à l'exécution (peu probable). Si vous en avez encore besoin, déplacez simplement l'appel vers une classe distincte qui utiliserait le conteneur DI spécifique.

0

Y a-t-il une raison pour laquelle vous ne pouvez pas créer de classe personnalisée avec le constructeur souhaité, puis instancier un objet de cette classe dans votre fichier asmx, puis déléguer toute l'action à cet objet?

Je crée généralement ce genre d'objets comme celui-ci:

var o = CustomClass.Create(); 

public class CustomClass 
{ 
    public static CustomClass Create() 
    { 
    return IoC.Resolve<CustomClass>(); 
    } 
} 

public static class IoC 
{ 
    public T Resolve<T>() 
    { 
    return yourStaticReferenceToPreferredContainer.Resolve<T>(); 
    } 
} 
Questions connexes