Sono confuso sull'implementazione di Dependency Injection in un esempio concreto.Utilizzo di Abstract Factory che viene iniettato tramite il contenitore DI
Diciamo che abbiamo una classe SomeClass che ha una dipendenza di tipo IClassX.
public class SomeClass
{
public SomeClass(IClassX dependency){...}
}
Creazione di implementazioni concrete di interfaccia IClassX dipende dal parametro di runtime N.
Con dato costruttore, non riesco a configurare il contenitore DI (l'Unità è utilizzato), perché io non so cosa attuazione IClassX verrà utilizzato in runtime. Mark Seemann nel suo libro Dependency Injection In .Net suggerisce che dovremmo usare Abstract Factory come parametro di iniezione.
Ora abbiamo SomeAbstractFactory che restituisce le implementazioni di IClassX in base al parametro runtime runTimeParam.
public class SomeAbstractFactory
{
public SomeAbstractFactory(){ }
public IClassX GetStrategyFor(int runTimeParam)
{
switch(runTimeParam)
{
case 1: return new ClassX1();
case 2: return new ClassX2();
default : return new ClassDefault();
}
}
}
SomeClass ora accetta ISomeAbstractFactory come parametro di iniezione:
public class SomeClass
{
public SomeClass(ISomeAbstractFactory someAbstractfactory){...}
}
e va bene. Abbiamo una sola radice di composizione in cui creiamo il grafico dell'oggetto. Configuriamo il contenitore Unity per iniettare SomeAbstractFactory su SomeClass.
Ma, supponiamo che le classi ClassX1 e ClassX2 hanno le loro dipendenze:
public class ClassX1 : IClassX
{
public ClassX1(IClassA, IClassB) {...}
}
public class ClassX2 : IClassX
{
public ClassX2(IClassA, IClassC, IClassD) {...}
}
come risolvere IClassA, IClassB, IClassC e IClassD dipendenze?
1. iniezione attraverso il costruttore SomeAbstractFactory
Ci può iniettare implementazioni concrete di IClassA, IClassB, IClassC e IClassD a SomeAbstractFactory in questo modo:
public class SomeAbstractFactory
{
public SomeAbstractFactory(IClassA classA, IClassB classB, IClassC classC, IClassD classD)
{...}
...
}
contenitore Unità sarebbe stato utilizzato nella fase iniziale composizione radice e quindi utilizzare DI DI uomo povero per restituire calcestruzzo ClassX1 o ClassX2 in base al parametro runTimeParam
public class SomeAbstractFactory
{
public SomeAbstractFactory(IClassA classA, IClassB classB, IClassC classC, IClassD classD){...}
public IClassX GetStrategyFor(int runTimeParam)
{
switch(runTimeParam)
{
case 1: return new ClassX1(classA, classB);
case 2: return new ClassX2(classA, classC, classD);
default : return new ClassDefault();
}
}
}
problemi con questo approccio:
- SomeAbstractFactory sa di dipendenze che don `t realmente ne fanno parte.
- Deeper grafico oggetto richiederebbe di modificare sia costruttore e classe di implementazione SomeAbstractFactory
- DI contenitore non sarebbe usato per risolvere le dipendenze, poveri man`s DI deve essere utilizzato
2. chiamata esplicita a DI container
Invece di "newing up" ClassX1 o ClassX2, li risolveremo utilizzando un contenitore DI.
public class SomeAbstractFactory
{
public SomeAbstractFactory(IUnityContainer container){...}
public IClassX GetStrategyFor(int runTimeParam)
{
switch(runTimeParam)
{
case 1: return container.Resolve<IClassX>("x1");
case 2: return container.Resolve<IClassX>("x2");
default : return container.Resolve<IClassX>("xdefault");
}
}
}
problemi con questo approccio:
- contenitore DI viene passato in SomeAbstractFactory
- DI metodo Resolve non è usata solo alla radice composizione (ServiceLocator anti-modello)
C'è un altro approccio più adatto?