Eigentlich ist der "richtige" Weg, KEINE Fabrik zu benutzen, es sei denn, es gibt absolut keine andere Wahl (wie bei Unit-Tests und bestimmten Mocks - für Produktionscode verwenden Sie KEINE Fabrik)! Dies ist eigentlich ein Anti-Pattern und sollte unter allen Umständen vermieden werden. Der springende Punkt hinter einem DI-Container ist, dass das Gadget die Arbeit für Sie erledigt.
Wie bereits in einem früheren Beitrag erwähnt, soll Ihr IoC-Gadget die Verantwortung für die Erstellung der verschiedenen abhängigen Objekte in Ihrer App übernehmen. Das heißt, Sie lassen Ihr DI-Gadget die verschiedenen Instanzen selbst erstellen und verwalten. Dies ist der springende Punkt hinter DI - Ihre Objekte sollten NIEMALS wissen, wie sie die Objekte erstellen und / oder verwalten, von denen sie abhängen. Andernfalls bricht die Kupplung ab.
Das Konvertieren einer vorhandenen Anwendung in alle DIs ist ein großer Schritt. Abgesehen von den offensichtlichen Schwierigkeiten sollten Sie jedoch auch (um Ihr Leben ein wenig zu vereinfachen) ein DI-Tool ausprobieren, das den Großteil Ihrer Bindungen automatisch ausführt (Der Kern von Ninject sind die "kernel.Bind<someInterface>().To<someConcreteClass>()"
Aufrufe, die Sie ausführen , um Ihre Schnittstellendeklarationen mit den konkreten Klassen abzugleichen , die Sie zum Implementieren dieser Schnittstellen verwenden möchten. Es sind diese "Bind" -Aufrufe, mit denen Ihr DI-Gadget Ihre Konstruktoraufrufe abfangen und die bereitstellen kann Erforderliche abhängige Objektinstanzen Ein typischer Konstruktor (Pseudocode hier gezeigt) für eine Klasse könnte sein:
public class SomeClass
{
private ISomeClassA _ClassA;
private ISomeOtherClassB _ClassB;
public SomeClass(ISomeClassA aInstanceOfA, ISomeOtherClassB aInstanceOfB)
{
if (aInstanceOfA == null)
throw new NullArgumentException();
if (aInstanceOfB == null)
throw new NullArgumentException();
_ClassA = aInstanceOfA;
_ClassB = aInstanceOfB;
}
public void DoSomething()
{
_ClassA.PerformSomeAction();
_ClassB.PerformSomeOtherActionUsingTheInstanceOfClassA(_ClassA);
}
}
Beachten Sie, dass sich an keiner Stelle in diesem Code ein Code befand, der die Instanz von SomeConcreteClassA oder SomeOtherConcreteClassB erstellt / verwaltet / freigegeben hat. Tatsächlich wurde keine konkrete Klasse erwähnt. Also ... wo ist die Magie passiert?
Im Start-Teil Ihrer App hat Folgendes stattgefunden (dies ist wiederum Pseudo-Code, aber er kommt dem echten (Ninject-) Ding ziemlich nahe ...):
public void StartUp()
{
kernel.Bind<ISomeClassA>().To<SomeConcreteClassA>();
kernel.Bind<ISomeOtherClassB>().To<SomeOtherConcreteClassB>();
}
Dieser kleine Code fordert das Ninject-Gadget auf, nach Konstruktoren zu suchen, diese zu scannen, nach Instanzen von Schnittstellen zu suchen, für die es konfiguriert wurde (das sind die "Bind" -Aufrufe), und dann eine Instanz der konkreten Klasse überall zu erstellen und zu ersetzen Die Instanz wird referenziert.
Es gibt ein nettes Tool, das Ninject sehr gut ergänzt und Ninject.Extensions.Conventions (ein weiteres NuGet-Paket) heißt und den Großteil dieser Arbeit für Sie erledigt. Nicht von den hervorragenden Lernerfahrungen abzulenken, die Sie während des Aufbaus selbst miterleben werden, aber um sich an die Arbeit zu machen, ist dies möglicherweise ein Hilfsmittel, um dies zu untersuchen.
Wenn Speicher zur Verfügung steht, verfügt Unity (offiziell von Microsoft, jetzt ein Open Source-Projekt) über einen oder zwei Methodenaufrufe, die dasselbe tun. Andere Tools verfügen über ähnliche Hilfsprogramme.
Welchen Weg Sie auch wählen, lesen Sie unbedingt Mark Seemanns Buch für den Großteil Ihres DI-Trainings. Es sollte jedoch darauf hingewiesen werden, dass selbst die "Großen" der Welt der Softwaretechnik (wie Mark) grelle Fehler machen können - Mark hat alles vergessen Ninject in seinem Buch. Hier ist eine weitere Ressource, die nur für Ninject geschrieben wurde. Ich habe es und es ist eine gute Lektüre: Mastering Ninject for Dependency Injection