1

Lors de l'utilisation d'un conteneur d'injection de dépendances, des dépendances manquantes sont détectées lors de l'exécution de la résolution. C'est à l'exécution.Détermination statique des dépendances manquantes lors de l'utilisation du conteneur d'injection de dépendances

Cet article décrit une solution partielle. Il contribuerait à simplifier test, le débogage et la maintenance, mais il faut encore des tests à exécuter pour valider votre comportement (en particulier si vous utilisez la sous-solution d'usine abstraite pour la résolution d'exécution):

http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

Lorsque En utilisant des conteneurs d'injection de dépendances, existe-t-il un moyen de déterminer statiquement que toutes vos dépendances seront résolues?

Répondre

2

Réponse courte: non, cela ne peut pas être fait. Pour cela, il faudrait pouvoir représenter tous les composants et leurs dépendances (les métadonnées du conteneur) sous la forme d'un graphique, afin de l'analyser. Le problème est que plus le conteneur est sophistiqué, plus il est difficile d'y parvenir. Prenez par exemple Windsor. Ses numerous extension points rendent les dépendances trop dynamiques pour être représentées sous forme de graphe. Les chargeurs de composants paresseux, les sélecteurs de gestionnaire, les usines, les contributeurs de composant, les sous-résolveurs, tous participent au processus et peuvent être du code utilisateur arbitraire, ce qui rend l'analyse statique impossible.

Une analyse statique pourrait être réalisable pour un conteneur trivial, mais alors ce conteneur hypothétique serait plutôt inutile pour les projets réels. Comme d'habitude, c'est un compromis, et le mieux que nous puissions faire est d'avoir des tests qui exercent la résolution réelle de tous les composants enregistrés dans le conteneur. StructureMap a une méthode AssertConfigurationIsValid() pour faire exactement cela.

Même ainsi, il pourrait y avoir plus d'erreurs subtiles qui ne sont pas attrapées par cela, comme lifestyle issues.

+0

Les meilleures pratiques sont définitivement intéressantes et utiles pour moi. Il se trouve que je regarde Windsor, ce qui est particulièrement pertinent pour moi. Merci pour les liens utiles :) –

5

Le cadre d'extensibilité géré (MEF, Managed Extensibility Framework) peut le faire. Il y a quelques bonnes pratiques que vous devez respecter pour que l'analyse soit précise, mais les résultats sont par ailleurs bons.

Pour analyser un ensemble d'assemblys, un outil de ligne de commande est utilisé - voir http://blogs.msdn.com/b/nblumhardt/archive/2009/08/28/analyze-mef-assemblies-from-the-command-line.aspx. Cela peut être exécuté à partir de Visual Studio ou d'un script de génération dans un serveur d'intégration continue - http://blogs.msdn.com/b/nblumhardt/archive/2009/09/24/debug-composition-from-within-visual-studio.aspx.

Vous pouvez le faire visuellement (à nouveau sur un ensemble d'assemblages) en utilisant Visual MEFX de projet MefContrib - voir http://xamlcoder.com/blog/2010/04/10/updated-visual-mefx/

MEF prend en charge cette fonctionnalité en étant à la fois très déclaratives (attributs standard pour la configuration) et en utilisant un sous-jacent modèle de composition qui fonctionne paresseusement (il peut construire le graphique sans créer d'instances ... Prend un peu pour envelopper votre tête autour.)

+0

Cool! Je n'ai jamais pensé que ce serait possible. Cependant, pour être honnête, il devrait être * possible à Windsor car il représente aussi des composants sous forme de nœuds de graphes, mais seulement pour une utilisation très restreinte/statique du conteneur ... –

+0

Oui, il s'agit plutôt de la portée de ce qui peut être analysé plutôt qu'une question de tout ou rien. MEF va un peu plus loin en faisant des choses comme l'équivalent de la facilité d'usine dactylographiée capable d'être analysé. Sera intéressant de voir ce que Krzysztof a cuisiné pour Windsor v.3 :) –

1

En plus de ce que Mauricio a dit, Windsor 2.5 a une fonctionnalité que vous pourriez trouver utile quand diagnostiquer des problèmes avec des dépendances manquantes ou simplement regarder à travers les composants dans le conteneur. J'ai blogué sur la version bêta de here. C'est maintenant beaucoup plus utile et comme tout à Windsor - c'est extensible afin que vous puissiez sortir vos propres articles sur cette liste.

alt text

0

Peut-être pas avec un conteneur d'injection de dépendance. Cependant, vous pouvez effectuer une injection de dépendance manuellement, sans conteneur. Par exemple:

var foo = new Foo(); 
var bar = new Bar(foo); 
var program = new Program(bar); 
program.Run(); 

S'il se compile alors toutes les dépendances sont là. Cependant, des problèmes surgissent dès que le graphe de dépendance devient assez grand pour que vous ne puissiez pas le garder entièrement dans votre tête (en particulier avec certaines dépendances circulaires dans le mixage). Si vous faites des refactorings qui impliquent le réarrangement des dépendances, alors il deviendra difficile d'adapter l'ordre des appels du constructeur.

+0

Bien que j'apprécie ta réponse, elle ne m'est pas terriblement utile :) Je veux que le code de mon équipe sépare la construction des dépendances et l'accès aux dépendances. Cette utilisation de DI le rend facile à oublier, ou à glisser involontairement. C'est pourquoi je vais préconiser l'utilisation d'un conteneur DI et/ou d'usines abstraites. –

+0

@Merlyn: Je ne comprends pas vraiment ce que tu veux dire. L'injection de dépendance manuelle maintient la phase de construction séparée du reste du code exactement de la même manière qu'avec un conteneur. L'extrait de code ci-dessus est équivalent à ce que 'var programme = container.Resolve ();' ferait, et apparaîtrait au même endroit dans le code. –

+0

Désolé, je devrais me corriger. Quand j'ai dit accès, je voulais dire remplir une fente de dépendance. J'utilise ceci comme une solution pour l'isolation de test, donc je peux injecter des simulacres. À moins que je ne résume la dépendance exacte transmise au code, je suis bloqué avec l'implémentation que le code appelant a transmise. Les deux solutions que je connais sont des classes d'usine abstraites (ce qui me permettrait de faire la vérification statique que vous décrivez ici) et des conteneurs DI (ce qui est ma question). Je prévois déjà d'utiliser l'injection du constructeur dans les deux cas. –