Ich bin verwirrt über Dependency Injection-Implementierung in einem konkreten Beispiel.Arbeiten mit Abstract Factory, die durch DI-Container injiziert wird
Nehmen wir an, wir haben eine SomeClass-Klasse, die eine Abhängigkeit vom Typ IClassX hat.
public class SomeClass
{
public SomeClass(IClassX dependency){...}
}
Erstellung von konkreten Implementierungen von IClassX Schnittstelle ist abhängig von Laufzeitparameter N.
Mit gegeben Konstruktor, kann ich nicht DI-Container konfigurieren (Unity verwendet wird), weil ich nicht weiß, was die Umsetzung von IClassX wird zur Laufzeit verwendet. Mark Seemann in seinem Buch Dependency Injection In. Net schlägt vor, dass wir Abstract Factory als Injektionsparameter verwenden sollten.
Jetzt haben wir SomeAbstractFactory, die Implementierungen von IClassX basierend auf dem Runtime-Parameter runTimeParam zurückgibt.
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 akzeptiert nun ISomeAbstractFactory als Injektionsparameter:
public class SomeClass
{
public SomeClass(ISomeAbstractFactory someAbstractfactory){...}
}
Und das ist in Ordnung. Wir haben nur eine Kompositionswurzel, in der wir das Objektdiagramm erstellen. Wir konfigurieren den Unity-Container so, dass SomeAbstractFactory in SomeClass eingefügt wird.
Aber nehmen wir an, dass Klassen ClassX1 und ClassX2 ihre eigenen Abhängigkeiten:
public class ClassX1 : IClassX
{
public ClassX1(IClassA, IClassB) {...}
}
public class ClassX2 : IClassX
{
public ClassX2(IClassA, IClassC, IClassD) {...}
}
Wie IClassA, IClassB, IClassC und IClassD Abhängigkeiten lösen?
1. Injektion durch SomeAbstractFactory Konstruktor
können wir konkrete Implementierungen von IClassA, IClassB, IClassC und IClassD injizieren, so SomeAbstractFactory:
public class SomeAbstractFactory
{
public SomeAbstractFactory(IClassA classA, IClassB classB, IClassC classC, IClassD classD)
{...}
...
}
Unity Container würde in der Anfangs verwendet werden Zusammensetzung Wurzel und dann verwenden Sie DI des armen Mannes, um konkrete ClassX1 oder ClassX2 basierend auf Parameter 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();
}
}
}
zurückzugeben
Probleme mit diesem Ansatz:
- SomeAbstractFactory weiß um Abhängigkeiten, die wirklich zu ihr gehören `t.
- Deeper Objektgraphen würde erfordern, sowohl SomeAbstractFactory Konstruktor und Klassenimplementierung würde nicht verwendet werden
- DI-Container ändern Abhängigkeiten zu lösen, muß armen Mann `s DI
2. expliziten Aufruf DI verwendet werden Container
Anstatt ClassX1 oder ClassX2 neu zu erstellen, würden wir sie mithilfe eines DI-Containers beheben.
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");
}
}
}
Probleme mit diesem Ansatz:
- DI Behälter in SomeAbstractFactory geben wird
- DI Resolve Verfahren nicht nur an der Zusammensetzung Wurzel (Servicelocator anti-Muster)
verwendet wird Gibt es einen anderen geeigneten Ansatz?