2010-01-28 7 views
3

Il est parfois nécessaire d'utiliser l'injection de dépendance pour fournir les paramètres à utiliser dans le constructeur. C'est quelque chose qui est pris en charge dans Unity (et d'autres conteneurs d'injection de dépendance), de sorte que lorsqu'il essaie de créer une instance du type, il peut fournir vos arguments en tant que paramètres dans le constructeur.Passage des paramètres du constructeur lors de la résolution des types dans Unity: Meilleure pratique

Ma question est la suivante: cette approche est-elle souhaitable?

Au sein d'une interface, il est impossible de spécifier quels paramètres une classe d'exécution doit avoir. En spécifiant les paramètres à Unity, vous supposez que la classe d'implémentation possède ces paramètres et vous placez des contraintes implicites sur les futures classes d'implémentation. Ces contraintes ne peuvent pas être communiquées via l'interface.

Alors, est-ce est défaut dans la façon dont s'interfaces sont spécifiées (.NET), par exemple. devrait-il être possible de spécifier des signatures de constructeur? Ou est-ce que cette fonctionnalité (d'être capable de fournir des paramètres constructeurs) a été incluse dans Unity en raison d'un autre besoin?

La seule véritable approche réaliste (me) semble utiliser une usine pour créer les classes de mise en œuvre, et faire l'injection de dépendance à l'usine.

J'apprécie ma question ici peut-être pas clair, alors je vais demander un peu différemment: quelle est la meilleure façon de faire l'injection de dépendance à l'égard d'une classe qui a un constructeur exigeant des paramètres?

(je ne crois pas que cette question est subjective, car il devrait probablement être un modèle de conception unique pour ce type d'injection de dépendance.)

EDIT:

Je dois ajouter que mon principal problème est que je peux créer une nouvelle classe d'implémentation qui a des paramètres constructeurs supplémentaires (où les paramètres du constructeur ne sont pas des choses qui peuvent être créées par l'unité).

Répondre

0

La responsabilité des conteneurs IoC (dire l'unité) est de connecter des interfaces avec des applications concrètes. Cela signifie que votre conteneur doit connaître l'interface et comment créer l'objet qui implémente l'interface. L'utilisation de l'injection du constructeur est parfaitement légale et recommandée. Unity créera l'implémentation concrète lorsque votre application demandera une interface via la méthode Resolve(). Le conteneur Unity lui-même est la fabrique qui crée vos objets, vous utilisez Unity car vous ne voulez pas implémenter ces usines vous-même.

+0

Mais lorsque le constructeur nécessite des variables d'instance, je dois les fournir à Unity moi-même. Mais l'interface ne spécifie pas que j'ai besoin de ces paramètres, et si je crée une implémentation concrète de l'interface qui a des paramètres supplémentaires dans le constructeur? –

2

Je ne sais pas où vous avez eu l'idée que l'injection du constructeur ne correspond pas à DI. Je dirais que la situation réelle est à l'opposé de cela: injection de constructeur est l'un des modèles les plus courants utilisés pour réaliser l'injection de dépendance - j'irais jusqu'à dire que c'est le modèle le plus commun, et cette vue est certainement corroboré par le fait que la majorité des conteneurs d'inversion de contrôle (conteneurs DI) utilisent l'injection du constructeur comme mécanisme préféré.

StructureMap par exemple, a un noyau très spécifique pour le soutien injection constructeur où il choisira le constructeur avec le plus paramètres que le constructeur utilisé pour la résolution de la dépendance. Ce que vous dites en utilisant le modèle d'injection du constructeur est que "je supprime les dépendances codées en dur dans ma classe en les spécifiant comme des paramètres passés dans le constructeur - ma classe ne peut pas être instanciée sans ces dépendances". Bien sûr, la première moitié de cette déclaration est l'essence de DI, mais la seconde moitié applique plus.

Les dépendances sont un détail de mise en œuvre qui devrait pouvoir être facilement modifié, fournissant une solution flexible et faiblement couplée. Ils sont sur le comment, pas le quoi. Les interfaces spécifient le quoi. Donc, je dirais que votre suggestion de spécifier des dépendances dans les interfaces va en fait à l'encontre du concept d'injection de dépendance. Et en ce qui concerne votre déclaration sur les usines - c'est exactement ce que sont les conteneurs IOC - de grandes grandes usines qui prennent en charge l'arbre de dépendance d'une solution, donc vous n'avez pas besoin de vous en soucier.

Modifier

Je pense que peut-être vous demandez sur le cas où vous souhaitez fournir un paramètre constructeur non la dépendance, comme une carte d'identité pour une entité de référence, ou un état initial ENUM?

Personnellement, je ne vois pas de problème avec un conteneur IOC permettant cela. C'est toujours l'état initial de votre classe et par conséquent les règles pour la création de cet état doivent être explicitement exprimées. Cela peut signifier que vous avez parfois besoin de plus de références à votre conteneur IOC que vous pourriez aimer, mais ce n'est pas une situation assez horrible pour abandonner les autres avantages de l'injection counstructor.

+0

Vous avez raison dans votre édition - je fais référence aux paramètres du constructeur qui sont des instances de classe spécifiques ou des types de valeurs, pas des choses que le conteneur IOC résoudra en créant de nouvelles instances. –

0

Le problème ici est la définition de l'InjectionConstructor dans Unity par rapport à celle de Castle.Windsor. Dans Unity, si vous avez besoin d'injecter un paramètre particulier, par exemple un AppSetting, vous devez également fournir tous les autres paramètres, fixant ainsi la signature du constructeur. Cependant, dans Castle.Windsor, il prend le paramètre que vous avez fourni et utilise ensuite le mécanisme de résolution pour localiser les autres paramètres de la manière normale.

Il serait possible de l'introduire dans Unity en écrivant une stratégie de Builder personnalisée qui a fait une approche «best-fit» à utiliser par le constructeur plutôt que par défaut, tout ce qui est par défaut.

Questions connexes