0

Notre équipe a construit une application DDD qui a une couche de service d'application fortement définie qui est construite comme "l'API" du système. Il gère l'ensemble du domaine et de l'infrastructure pour accomplir des tâches génériques. Il n'utilise que des DTO comme entrée/sortie, de sorte que le domaine n'est jamais exposé au-delà de cette couche.Dois-je abstraire la configuration d'un conteneur IOC de l'interface utilisateur?

Maintenant, nous voulons ajouter un conteneur d'injection de dépendance dans le mélange et nous sommes confrontés à des choix difficiles. Nous avons deux applications clientes qui utilisent les services d'application pour faire leur travail: une application MVC 2 et une application de service Windows. Traditionnellement, tout le code de configuration pour effectuer le travail d'injection de dépendances est placé dans le fichier global.asax du projet mvc, dont j'ai vu de nombreux exemples. Le problème est que le code d'enregistrement IOC est ensuite dupliqué dans le service Windows et modifié légèrement pour cette plate-forme.

Le problème est que je DI nécessite l'application cliente pour savoir quoi et comment enregistrer, ce qui nécessite également l'application cliente d'avoir des références aux couches de domaine et de l'infrastructure. L'idée d'avoir une couche de services d'application était que c'était la seule chose que les clients devraient savoir et à qui parler. Ma solution proposée était de créer un «service de dépendance» dans ma couche de service d'application que les clients appellent une fois, et il configurerait le conteneur DI puisqu'il sait ce qui est requis. Il aurait également des méthodes pour permettre à l'application cliente d'enregistrer ses propres dépendances supplémentaires. Par exemple, le projet MVC enregistrerait sa fabrique de contrôleurs et le service Windows enregistrerait sa classe de démarrage. Je voulais savoir si cela est rare ou si je suis sur le mauvais chemin avec cette idée. Quelqu'un d'autre a-t-il déjà rencontré ce problème?

Répondre

2

Je mis une classe de configuration dans mon projet DDD ou DomainModel et appeler la classe de configuration dans l'interface utilisateur.

public static class IoCConfigurator() 
{ 
    public static void Initialize() 
    { 
     // your code here 
    } 
} 

Dans votre interface utilisateur, vous devez appeler uniquement la méthode Initialize() et c'est tout. Vous pouvez l'utiliser dans votre MVC Global.asax et même dans votre application de service Windows. Aucune duplication de code.

Fonctionne très bien pour moi.

+0

Comment enregistrer des types spécifiques au Web, par exemple, de cette façon? IoCConfigurator n'aura-t-il pas besoin de connaître et d'être lié à tous les différents environnements d'exécution possibles? Si vous devez enregistrer des contrôleurs MVC dans le conteneur sous l'hôte Web, vous ne souhaitez probablement pas les enregistrer (ni même déployer l'assembly) sur l'hôte du processus de service. –

+0

Cela dépend de quelle partie de mon projet est impliqué. Si j'ai besoin d'IoC dans mon projet DomainModel, je vais créer un IoCConfigurator pour ces dépendances spéciales dans ce projet. Si j'ai également besoin d'IoC dans mon projet WebUI MVC, je créerai également un IoCConfigurator pour ce projet. J'essaie de faire en sorte que le projet soit le moins possible couplé. Par exemple, lorsque j'ai besoin de l'assembly DomainModel dans mon projet WebService, je ne gère pas les éléments de configuration IoC manuellement. Je suppose qu'il existe un configurateur pour les dépendances spécifiques dans cet assembly. – Mariusz

3

Il existe plusieurs façons de peler un chat; il semble que vous prenez la mauvaise approche cependant. Le point d'entrée de l'application (Global.asax ou Program.cs) doit absolument être l'emplacement qui sélectionne les composants à configurer dans le conteneur IoC. D'un autre côté, vos services ne devraient généralement pas contenir de connaissances en matière de configuration IoC. Je suppose que vous suivez déjà ce principe mais que vous le réexaminez à cause de la configuration répétitive.

Pour que cela soit possible sans répétition de code, comme vous l'avez décrit, de nombreux conteneurs IoC fournissent des constructions de modularisation qui encapsulent la configuration d'un ensemble de composants connexes. Dans Autofac (et Ninject IIRC), ils sont appelés «modules» - http://code.google.com/p/autofac/wiki/StructuringWithModules. Castle Windsor les appelle «installateurs» tandis que StructureMap les appelle «registres».

En configuration factorisation en modules, la quantité de code de configuration dans le mode de démarrage de l'application est réduite. Dans votre exemple, comme une simplification, vous pouvez créer trois modules:

  • CoreModule
  • WebModule
  • ServiceProcessModule

Le CoreModule contiendrait la configuration des composants qui sont partagés et se comportent de manière identique dans chacun des environnements d'exécution.WebModule et ServiceProcessModule contiendraient des enregistrements pour les composants spécifiques à ces environnements, ainsi qu'une configuration spécialisée de tous les composants partagés qui sont configurés différemment en fonction de l'hôte.

démarrage de votre application web serait alors quelque chose comme:

foo.RegisterModule<CoreModule>(); 
foo.RegisterModule<WebModule>(); 
// Resolve root component, run app 

Alors que le processus de service serait très similaire, mais en remplaçant WebModule pour ServiceProcessModule.

Ce style de configuration s'adaptera beaucoup mieux à de nombreux points d'entrée d'application et/ou à de nombreux sous-systèmes de composants, par rapport à la méthode d'initialisation statique avec un code conditionnel.

Espérons que cela aide. Nick

+0

+1 pour la modularisation. J'ai utilisé Spring.net-Xml-Configuration et j'avais un fichier configfile par module et un fichier de config qui référence les fichiers module-config. Cette approche est simmilar à Nicolas aproach – k3b

+0

Comment cela résout-il la duplication? Chaque "installateur" ou "module" devrait être créé quelque part. Si c'est dans l'application client, je devrais répéter cela pour chaque application client. C'est la même situation. Est-ce que je les définis dans la couche de service d'application? Ensuite, il est interdit d'avoir une configuration IOC dans la couche de service de l'application. – Jason