2010-02-11 9 views
8

J'ai une classe qui a des dépendances que j'ai branchées avec Ninject. Dans l'implémentation réelle, j'utilise l'injection de propriété, mais pour illustrer rapidement, je vais injecter sur le terrain. Si je comprends bien, au lieu des instances Newing de MyObject, afin d'obtenir les dépendances soient correctement injectés, je dois utiliserCréation de noyau Ninject dans une bibliothèque de classes

kernel.Get<MyObject>() 

La chose que je suis trébuchant sur est cependant que MyObject ne sera utilisé que dans le contexte d'une bibliothèque de classes. L'intention est que les applications finales créent leurs propres modules et les transmettent à une instance de noyau pour s'hydrater. Compte tenu de cela, quelle est généralement la manière la plus pragmatique d'approcher une instance générique d'un noyau Ninject dans ma bibliothèque de classes pour que les instances de MyObject (et d'autres cas similaires) puissent être hydratées? Ma première inclination est une sorte d'usine qui internalise un noyau singleton - que les applications elles-mêmes doivent hydrater/initialiser en chargeant un module.

Ainsi, dans RandomService.cs

var myKernel = NinjaFactory.Unleash(); 
var myobj = myKernel.Get<MyObject>(); 
myobj.foo(); 

Avant d'aller trop loin dans cette voie cependant, je dois faire une vérification de bon sens pour vous assurer que la pensée est saine ou qu'il n'y a pas un autre évident chose que je manque. Je suis évidemment nouveau à IoC et j'ai l'impression d'avoir les bases, mais pas forcément les meilleures façons de l'utiliser.

Répondre

9

Je ne suis pas sûr de comprendre tous les détails de votre question, mais pour autant que je comprends, vous demandez comment vous pouvez externaliser la dépendance sur Ninject.

Il est possible d'écrire DI-friendly libraries without ever referencing any particular DI Container (Ninject ou toute autre chose). Cela laisse le consommateur de la bibliothèque ouvert pour choisir le conteneur DI de son goût (ou ne pas utiliser de conteneur du tout). Cette approche est très préférée car elle offre un plus grand degré de liberté.

Cependant, vous devriez vraiment favoriser Constructor Injection sur Injection de propriété. Bien que l'injection de propriété semble être d'une simplicité trompeuse à mettre en œuvre, il est en réalité assez difficile d'y arriver. L'un des grands avantages de l'injection de constructeurs est que vous n'avez pas besoin de mettre d'attributs sur le constructeur car il contient déjà toutes les informations nécessaires pour qu'un conteneur DI puisse le câbler correctement.

+0

Heureusement, c'est un lib interne (dans un sens corporatif) donc j'ai un public captif - d'autres développeurs de mon équipe, en utilisant un outil standard. Maintenant, chaque dev peut avoir des liaisons différentes qu'ils veulent, d'où mon problème initial. Re: ctor vs injection prop, prop semble certainement avoir beaucoup de cruft je dois écrire, mais je m'inquiète de la liste de dépendance croissante au fil du temps et donc les appels ctor. Y a-t-il d'autres inconvénients à l'injection d'accessoires que je devrais surveiller? – bakasan

+2

Même avec une application interne, je suivrais toujours les mêmes principes car ils conduisent à un code plus propre avec une meilleure séparation des préoccupations. Il existe de nombreux problèmes potentiels avec Property Injection, notamment la protection des invariants (la dépendance est-elle nulle?), Le remplacement à chaud de la dépendance injectée (probablement pas quelque chose que vous voulez faire) et une API plus vague en général. –

+2

Oh, et juste pour être à l'avant et explicite à ce sujet: Je considère Service Locator un anti-pattern: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx –

4

Le point de Mark est définitivement ma vue de départ (d'où un +1) sur cela. NB n'oubliez pas de suivre son lien. Pour ma part, j'ai été coupable d'abandonner trop tôt le constructeur pour des propriétés (ou des champs) (mon «excuse» était que comme une classe de base avait besoin de 5 propriétés, je ne voulais pas imposer toutes les classes dérivées La solution consistait à enrouler les 5 propriétés impliquées dans une classe ou une hiérarchie de classes représentant les concepts sous-jacents représentés par les propriétés, un peu comme le refactoring de l'objet de paramètre Introduire.

Une bonne discussion des considérations que je trouvais utile est http://thinkbeforecoding.com/post/2009/05/15/IOC-container-go-hide (cant Localisez le poste SO qui mentionne et certains sujets autour de lui, peut-être quelqu'un Injecter un lien: D)

Un autre blog qui résume quelques-unes des ces points est Your IoC Container is Showing

Et http://davybrion.com/blog/2009/11/integrating-your-ioc-container-with-agatha/

0

Voici une belle recette d'usage général pour trouver tous les modules ninject dans l'assemblage actuel:

IKernel _serviceKernel = new StandardKernel(); 

Assembly myAssembly = this.GetType().Assembly; 

IEnumerable<Type> ninjectModuleTypes = 
    myAssembly.GetTypes().Where(type => type.BaseType == typeof(NinjectModule)); 

foreach (Type ninjectModuleType in ninjectModuleTypes) 
{ 
    NinjectModule mod = (NinjectModule)Activator.CreateInstance(ninjectModuleType); 
    _serviceKernel.Load(mod); 
}