2010-02-11 9 views
8

Ho una classe con dipendenze che ho cablato con Ninject.Nascondere la creazione del kernel all'interno di una libreria di classi

public interface IFoo {} 

public class MyObject { 
    [Inject] 
    IFoo myfoo; 
} 

In attuazione reale che sto utilizzando l'iniezione di proprietà, ma solo per illustrare in modo rapido, io iniettare sul campo. Mi pare di capire, invece di istanze Newing di MyObject, al fine di ottenere le dipendenze per essere adeguatamente iniettato, ho bisogno di usare

kernel.Get<MyObject>() 

La cosa che sto inciampando però è che MyObject sarà usato solo nel contesto di una libreria di classi. L'intenzione è per le applicazioni finali di creare i propri moduli e passarli in un'istanza del kernel per idratare. Detto questo, quale è in genere il modo più pragmatico di affrontare l'affioramento di un'istanza generica di un kernel di Ninject nella mia libreria di classi in modo che le istanze di MyObject (e altri casi simili) possano essere idratate?

La mia prima inclinazione è una sorta di factory che internalizza un kernel singleton - che le applicazioni stesse devono idratare/inizializzare caricando un modulo.

Quindi, in RandomService.cs

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

Prima di andare troppo lontano su questa strada, però, ho bisogno di fare un controllo di integrità per assicurarsi che il pensiero è suono o che non ci sia qualche altra evidente cosa che mi manca Sono ovviamente nuovo di IoC e mi sento come se fossi alle basi, ma non necessariamente il modo migliore di usarlo.

risposta

9

Non sono sicuro di aver compreso tutti i dettagli della domanda, ma per quanto ho capito, mi stai chiedendo come esternalizzare la dipendenza da Ninject.

È possibile scrivere DI-friendly libraries without ever referencing any particular DI Container (Ninject o qualsiasi altra cosa). Ciò lascia aperto il consumatore della biblioteca per scegliere il contenitore DI di suo gradimento (o non utilizzare affatto un contenitore). Questo approccio è molto preferito perché fornisce un maggiore grado di libertà.

Tuttavia, si dovrebbe davvero favorire Constructor iniezione oltre Proprietà iniezione. Sebbene Property Injection sia apparentemente ingannevolmente semplice da implementare, in realtà è piuttosto difficile ottenere il risultato giusto.

Uno dei grandi vantaggi di Constructor Injection è che non è necessario inserire alcun attributo nel costruttore perché strutturalmente dispone già di tutte le informazioni necessarie per un contenitore DI per cablarlo correttamente.

+0

Fortunatamente, questo è un lib interno (in senso aziendale) quindi ho un pubblico in cattività - altri sviluppatori del mio team, utilizzando uno strumento standard. Ora, ogni dev può avere legami diversi che desidera, da qui la mia originaria quandry. Re: ctor vs prop injection, l'elica sembra avere un sacco di cose da scrivere, ma mi preoccupo che la lista delle dipendenze cresca nel tempo e quindi le chiamate dei ctor. Ci sono altri svantaggi per puntellare l'iniezione che dovrei cercare? – bakasan

+2

Anche con un'app interna, continuerei a seguire gli stessi principi che portano a un codice più pulito con una migliore separazione delle preoccupazioni. Ci sono molti potenziali problemi con Property Injection, tra cui la protezione degli invarianti (è la dipendenza null?), Eventualmente lo swapping a caldo della dipendenza iniettata (probabilmente non qualcosa che si vuole fare) e una API più vaga in generale. –

+2

Oh, e solo per essere esplicito ed esplicito al riguardo: considero Service Locator un anti-pattern: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx –

4

Il punto di Mark è sicuramente la mia vista iniziale (quindi un +1) su questo. NB non dimenticare di seguire il suo collegamento.

Io per primo mi sono reso colpevole in passato di rinunciare al costruttore su proprietà (o campi) troppo presto (la mia "scusa" era che come classe base erano necessarie 5 proprietà che non volevo appesantire tutte le classi derivate con quella La soluzione era quella di racchiudere le 5 proprietà coinvolte in una classe o una gerarchia di classi che rappresentano i concetti sottostanti che le proprietà rappresentano, un po 'come il refactoring Introduce Parameter Object.

Una buona discussione delle considerazioni che ho trovato utile è http://thinkbeforecoding.com/post/2009/05/15/IOC-container-go-hide (Cant Individuare il SO post che menziona e alcuni argomenti intorno ad esso, forse qualcuno Iniettare un link: D)

Un altro blog che riassume alcune delle questi punti è Your IoC Container is Showing

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

0

Ecco una bella ricetta di uso generale per la ricerca di tutti i moduli Ninject nell'assieme corrente:

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); 
} 
Problemi correlati