2012-01-23 13 views
6

Sto cercando un Contenitore IoC veramente semplice e leggero il cui sorgente C# può essere incluso nel mio progetto (quindi non fare un riferimento esterno).Contenitore IoC incorporato nel progetto

Il motivo è che sto scrivendo un'infrastruttura e vorrei fornire un singolo file .dll, senza alcuna dipendenza aggiuntiva.

Anche io non voglio ILMerge mia montaggio con il gruppo IoC ..

ho pensato di MEF, alcuni altri suggerimenti?

+0

È possibile taggare questo .net per ulteriori suggerimenti. –

+1

guarda questa domanda: http://stackoverflow.com/questions/2515124/whats-the-simplest-ioc-container-for-c c'è un esempio online –

+6

Se stai scrivendo una biblioteca, non dovresti utilizzare un contenitore DI completamente: http://stackoverflow.com/questions/2045904/dependency-inject-di-friendly-library/2047657#2047657 –

risposta

3

Se si utilizza .NET 4.0, è incluso MEF.

Per .NET 2 Una volta ho scritto qualcosa di simile usando interfacce e Reflection. Ci sono molti tutorial là fuori che descrivono quel processo. Anche se è possibile utilizzare MEF, vale comunque la pena tentare alcuni tutorial di riflessione poiché questo è il modo in cui MEF funziona sotto.

Controllare anche la domanda this che ha alcune buone risposte. TinyIoC sembra proprio un unico file sorgente.

+0

Grazie per TinyIoC. Sembra esattamente quello che stavo cercando. – dux2

0

Mi piace molto Castle.Windsor che è open source, così si potrebbe aggiungere i file di codice relativi al progetto

+2

Windsor non è la mia definizione di contenitore leggero. Include circa 4 assiemi e molti file/classi sorgente. – dux2

0

Non è poi così difficile per rotolare il proprio contenitore, a seconda del tipo di caratteristiche che avete bisogno. È comunque molto facile creare perdite quando si fa così, quindi suppongo che vorresti probabilmente usare una soluzione collaudata.

MEF è utilizzato da alcuni come contenitore ma (da notare) altri dicono che MEF is not an IOC container, in sostanza MEF è stato progettato per essere un'architettura di plugin non un contenitore di dipendenze per l'iniezione.

Considerando tutto ciò, ti consiglio di incorporare il codice sorgente completo per il contenitore di tua scelta nella tua applicazione o di utilizzare uno strumento per unire il suo assieme nel tuo. ILMerge è uno strumento in grado di farlo, la maggior parte degli offuscatori commerciali può aiutarti a fare altrettanto. Se stai costruendo una libreria o un'applicazione commerciale, ti consiglio comunque di usare comunque un vero e proprio offuscatore.

+0

Come ho affermato nella mia domanda, sono disposto a incorporare il codice sorgente del contenitore nel mio progetto, ma sto cercando un contenitore testato con un numero minimo di file e classi. No ILMerge per favore. – dux2

+0

Quali sono i requisiti per il contenitore? Che tipo di supporto al ciclo di vita hai bisogno? Vuoi una configurazione XML, un'API di configurazione fluente o sei felice di configurare ciascun tipo in modo esplicito? –

+0

Mi piacerebbe configurare il contenitore tramite codice. Desidera il supporto per i cicli di vita singoli e transitori. – dux2

3

Se non avete bisogno di niente di eccezionale, un contenitore DI può essere davvero breve:

public class Container 
{ 
    private readonly Dictionary<Type,Func<Container,object>> factories; 
    private readonly Dictionary<Type,object> cache; 

    public Container() 
    { 
     this.factories = new Dictionary<Type,Func<Container,object>>(); 
     this.cache = new Dictionary<Type,object>(); 
    } 

    public void Register<TContract>(Func<Container,TContract> factory) 
    { 
     // wrap in lambda which returns object instead of TContract 
     factories[typeof(TContract)] = c => factory(c); 
    } 

    public TContract Get<TContract>() 
    { 
     var contract = typeof(TContract); 
     if (!cache.ContainsKey(contract)) 
     { 
      this.cache[contract] = this.factories[contract](this); 
     } 
     return (TContract)this.cache[contract]; 
    } 
} 

Quale si usa in questo modo:

var container = new Container(); 
container.Register<ICar>(c => new Car(
    c.Get<IEngine>(), c.Get<IWheel>())); 
container.Register<IWheel>(c => new Wheel()); 
container.Register<IEngine>(c => new Engine()); 

var car = container.Get<ICar>(); 

Ancora più minimalista sarebbe quella di fare la dipendenza iniezione senza un contenitore:

IWheel wheel = new Wheel(); 
IEngine engine = new Engine(); 
ICar car = new Car(engine, wheel); 

Tuttavia, per oggetti grafici complessi può rapidamente ottenere compli per mantenere l'ordine di costruzione corretto durante i refactoring. Il contenitore non ha questo problema.