(Lié à cette question, EF4: pourquoi la création de proxy doit-elle être activée lorsque le chargement différé est activé? ).
Je suis nouveau dans DI, alors soyez patient avec moi. Je comprends que le conteneur est chargé d'instancier tous mes types enregistrés, mais pour ce faire, il nécessite une référence à toutes les DLL de ma solution et à leurs références.
Si je n'utilisais pas de conteneur DI, je n'aurais pas à référencer la bibliothèque EntityFramework dans mon application MVC3, uniquement ma couche métier, qui ferait référence à ma couche DAL / Repo.
Je sais qu'en fin de compte, toutes les DLL sont incluses dans le dossier bin mais mon problème est de devoir le référencer explicitement via "ajouter une référence" dans VS afin de pouvoir publier un WAP avec tous les fichiers nécessaires.
Réponses:
Oui, c'est exactement la situation que DI s'efforce d'éviter :)
Avec un code étroitement couplé, chaque bibliothèque peut n'avoir que quelques références, mais celles-ci ont à nouveau d'autres références, créant un graphe profond de dépendances, comme ceci:
Du fait que le graphe de dépendance est profond, cela signifie que la plupart des bibliothèques glisser le long d' un grand nombre d'autres dépendances - par exemple , dans le diagramme, la bibliothèque C traîne Bibliothèque H, E Library, Bibliothèque J, M Library, Bibliothèque K et Bibliothèque N . Cela rend plus difficile la réutilisation de chaque bibliothèque indépendamment du reste - par exemple dans les tests unitaires .
Cependant, dans une application faiblement couplée, en déplaçant toutes les références vers la racine de composition , le graphe de dépendance est fortement aplati :
Comme l'illustre la couleur verte, il est maintenant possible de réutiliser la bibliothèque C sans faire glisser les dépendances indésirables.
Cependant, tout ce que dit, avec de nombreux conteneurs DI, vous n'avez d'ajouter des références difficiles à toutes les bibliothèques requises. Au lieu de cela, vous pouvez utiliser une liaison tardive sous la forme d'une analyse d'assemblage basée sur des conventions (préférée) ou d'une configuration XML.
Lorsque vous faites cela, cependant, vous devez vous rappeler de copier les assemblys dans le dossier bin de l'application, car cela ne se produit plus automatiquement. Personnellement, je trouve rarement que cela vaut la peine.
Une version plus élaborée de cette réponse peut être trouvée dans cet extrait de mon livre Dependency Injection, Principles, Practices, Patterns .
la source
Même lorsque vous utilisez un conteneur DI, vous n'avez pas à laisser votre projet MVC3 référencer EF, mais vous choisissez (implicitement) de le faire en implémentant la racine de composition (le chemin de démarrage où vous composez vos graphiques d'objets) dans votre projet MVC3. Si vous êtes très strict sur la protection de vos limites architecturales à l'aide d'assemblages, vous pouvez déplacer votre logique de présentation vers un autre projet.
Lorsque vous déplacez toute la logique liée à MVC (contrôleurs, etc.) du projet de démarrage vers une bibliothèque de classes, cela permet à cet assemblage de couche de présentation de rester déconnecté du reste de l'application. Votre projet d'application Web lui-même deviendra une coque très fine avec la logique de démarrage requise. Le projet d'application Web sera la racine de composition qui référence tous les autres assemblys.
L'extraction de la logique de présentation dans une bibliothèque de classes peut compliquer les choses lorsque vous travaillez avec MVC. Il sera plus difficile de tout câbler, car les contrôleurs ne sont pas dans le projet de démarrage (alors que les vues, les images, les fichiers css doivent probablement rester dans le projet de démarrage). Ceci est probablement faisable mais prendra plus de temps à mettre en place.
En raison des inconvénients, je conseille généralement de conserver simplement la racine de composition dans le projet Web. De nombreux développeurs ne veulent pas que leur assembly MVC dépende de l'assembly DAL, mais ce n'est pas vraiment un problème. N'oubliez pas que les assemblys sont un artefact de déploiement ; vous divisez le code en plusieurs assemblys pour permettre au code d'être déployé séparément. Une couche architecturale, en revanche, est un artefact logique . Il est très bien possible (et courant) d'avoir plusieurs couches dans le même assemblage.
Dans ce cas, nous finirons par avoir la racine de composition (couche) et la couche de présentation dans le même projet d'application Web (donc dans le même assemblage). Et même si cet assemblage fait référence à l'assemblage contenant la DAL, la couche de présentation ne fait toujours pas référence à la couche d' accès aux données . C'est une grande distinction.
Bien sûr, lorsque nous faisons cela, nous perdons la possibilité pour le compilateur de vérifier cette règle architecturale au moment de la compilation, mais cela ne devrait pas être un problème. La plupart des règles architecturales ne peuvent en fait pas être vérifiées par le compilateur et il y a toujours quelque chose comme le bon sens. Et s'il n'y a pas de bon sens dans votre équipe, vous pouvez toujours utiliser des révisions de code (ce que chaque équipe devrait toujours faire à l'OMI). Vous pouvez également utiliser un outil tel que NDepend (qui est commercial), qui vous aide à vérifier vos règles architecturales. Lorsque vous intégrez NDepend à votre processus de construction, il peut vous avertir lorsque quelqu'un a archivé du code qui enfreint une telle règle architecturale.
Vous pouvez lire une discussion plus élaborée sur le fonctionnement de la racine de composition dans le chapitre 4 de mon livre Injection de dépendances, principes, pratiques, modèles .
la source
Vous pouvez créer un projet séparé appelé "DependencyResolver". Dans ce projet, vous devez référencer toutes vos bibliothèques.
Désormais, la couche d'interface utilisateur n'a pas besoin de NHibernate / EF ou de toute autre bibliothèque non pertinente à l'interface utilisateur, à l'exception de Castle Windsor, pour être référencée.
Si vous souhaitez masquer Castle Windsor et DependencyResolver de votre couche d'interface utilisateur, vous pouvez écrire un HttpModule qui appelle le registre IoC.
Je n'ai qu'un exemple pour StructureMap:
DefaultControllerFactory n'utilise pas directement le conteneur IoC, mais il délègue aux méthodes de conteneur IoC.
Le
GetController
délégué est défini dans un registre StructureMap (à Windsor, il devrait s'agir d'un programme d'installation).la source
la source