Ich bin gewohnt, IoC / DI in Web-Anwendungen - vor allem Ninject mit MVC3. Mein Controller ist für mich erstellt, gefüllt mit allen Abhängigkeiten vor Ort, Subabhängigkeiten etc.
In einer Thick-Client-Anwendung sind die Dinge jedoch anders. Ich muss meine eigenen Objekte erstellen, oder ich muss zu einem Service-Locator-Stil-Ansatz zurückkehren, wo ich den Kernel (wahrscheinlich über eine Schnittstelle, um die Testbarkeit zu ermöglichen) frage, um mir ein Objekt mit Abhängigkeiten zu geben.
Ich habe jedoch mehrere Stellen gesehen, an denen Service Locator als Anti-Pattern beschrieben wurde.
Meine Frage ist also - wenn ich von Ninject in meiner Thick-Client-App profitieren möchte, gibt es einen besseren / richtigen Weg, all das zu bekommen?
Bitte beachten Sie, dass ich hier nicht nur von MVVM spreche und Modelle in Ansichten umwandele. Dies wird insbesondere dadurch ausgelöst, dass ein Objekt vom Typ repository vom Kernel bereitgestellt werden muss und Entitäten aus diesem Repository mit Funktionalität geladen werden müssen (die Daten stammen natürlich von der Datenbank, benötigen jedoch abhängig vom Status auch einige Objekte als Parameter) der Welt, und Ninject weiß, wie man das zur Verfügung stellt). Kann ich das irgendwie tun, ohne beide Repositories und Entitäten als untestable Messes zu verlassen?
Wenn etwas unklar ist, lass es mich wissen. Danke!
BEARBEITEN SIE AM 14. JULI
Ich bin mir sicher, dass die zwei Antworten wahrscheinlich richtig sind. Doch jede Faser meines Körpers kämpft gegen diese Veränderung. Einiges davon ist wahrscheinlich durch einen Mangel an Wissen verursacht, aber es gibt auch einen konkreten Grund, warum ich Schwierigkeiten habe, die Eleganz dieser Art zu sehen, Dinge zu tun;
Ich habe das in der ursprünglichen Frage nicht gut genug erklärt, aber die Sache ist, dass ich eine Bibliothek schreibe, die von mehreren (4-5, vielleicht später) WPF-Client-Anwendungen verwendet wird. Diese Anwendungen arbeiten alle nach dem gleichen Domänenmodell usw., daher ist es die einzige Möglichkeit, DRY zu verwenden, wenn Sie alles in einer einzigen Bibliothek aufbewahren. Es besteht jedoch auch die Möglichkeit, dass Kunden dieses Systems ihre eigenen Kunden schreiben - und ich möchte, dass sie eine einfache, saubere Bibliothek haben, mit der sie sprechen können. Ich möchte sie nicht dazu zwingen, DI in ihrer Composition Root zu verwenden (indem sie den Begriff wie Mark Seeman in seinem Buch verwenden) - weil HUGELY die Dinge im Vergleich zu ihnen komplizierter macht, indem sie einfach ein MyCrazySystemAdapter () neu erstellt und verwendet.
>Nun muss der MyCrazySystemAdapter (Name gewählt, weil ich weiß, dass die Leute hier nicht mit mir übereinstimmen) von Unterkomponenten zusammengesetzt und mit DI zusammengesetzt werden. MyCrazySystemAdapter selbst sollte nicht injiziert werden müssen. Es ist die einzige Schnittstelle, die die Clients verwenden müssen, um mit dem System zu sprechen. Also sollte ein Klient glücklicherweise eins von denen bekommen, DI passiert wie Magie hinter den Kulissen, und das Objekt wird von vielen verschiedenen Objekten mit Best Practices und Prinzipien zusammengesetzt.
Ich bin mir bewusst, dass dies ein kontroverser Weg ist, etwas zu wollen. Ich kenne aber auch die Leute, die Kunden dieser API sein werden. Wenn sie sehen, dass sie ein DI-System lernen und verkabeln müssen und ihre gesamte Objektstruktur im Anwendungseingangspunkt (Composition Root) vor der Zeit erstellen müssen, geben sie mir, anstatt ein einzelnes Objekt zu vergrößern, den Mittelfinger und Gehe direkt in die Datenbank und vermassele Dinge, die du dir kaum vorstellen kannst.
TL; DR: Die Bereitstellung einer ordnungsgemäß strukturierten API ist für den Client zu mühsam. Meine API muss ein einzelnes Objekt bereitstellen, das hinter den Kulissen mithilfe von DI und geeigneten Verfahren erstellt wird. Die reale Welt übertrifft manchmal den Wunsch, alles rückwärts zu bauen, um Mustern und Praktiken treu zu bleiben.
Ich schlage vor, MVVM-Frameworks wie Caliburn zu betrachten. Sie bieten eine Integration mit IoC-Containern.
Grundsätzlich sollten Sie die vollständige Anwendung in Ihrer app.xaml aufbauen. Wenn einige Teile später erstellt werden müssen, weil Sie noch nicht alles wissen, um sie beim Start zu erstellen, injizieren Sie eine Factory entweder als Schnittstelle (siehe unten) oder als Func (siehe Unterstützt Ninject Func (automatisch generierte Factory)? ) in der Klasse, die diese Instanz erstellen muss. Beide werden in der nächsten Ninject-Version nativ unterstützt.
z.B.
%Vor%Beachten Sie, dass die Factory-Implementierung logisch zur Containerkonfiguration und nicht zur Implementierung Ihrer Business-Klassen gehört.
Ich weiß nichts über WPF oder MVVM, aber Ihre Frage bezieht sich grundsätzlich darauf, wie Sie Material aus dem Container holen können, ohne einen Service Locator (oder den Container direkt) überall zu verwenden, richtig?
Wenn ja, kann ich Ihnen ein Beispiel zeigen.
Der Punkt ist, dass Sie stattdessen eine Factory verwenden, die den Container intern verwendet. Auf diese Weise verwenden Sie den Container tatsächlich nur an einer Stelle.
Hinweis: Ich werde ein Beispiel mit WinForms verwenden und nicht an einen bestimmten Container gebunden sein (weil, wie gesagt, ich WPF nicht kenne ... und Ich benutze Castle Windsor anstelle von NInject), aber da Ihre grundlegende Frage nicht spezifisch mit WPF / NInject verknüpft ist, sollte es für Sie einfach sein, meine Antwort an WFP / NInject zu "portieren".
Die Fabrik sieht so aus:
%Vor%Die Hauptform Ihrer App ruft diese Factory über die Konstruktorinjektion auf:
%Vor%Der Container wird initialisiert, wenn die App gestartet wird, und das Hauptformular wird aufgelöst (so erhält es die Factory über die Konstruktorinjektion).
%Vor%Jetzt kann das Hauptformular die Factory verwenden, um Dinge wie Ihr Repository aus dem Container zu holen:
%Vor%Wenn Sie mehr Formulare haben und die Factory auch von dort verwenden möchten, müssen Sie die Factory einfach in diese Formulare wie in das Hauptformular einfügen, die zusätzlichen Formulare beim Start registrieren und sie vom Hauptformular aus öffnen mit der Fabrik.
Wolltest du das wissen?
BEARBEITEN:
Ruben, natürlich hast du recht. Mein Fehler.
Das ganze Zeug in meiner Antwort war ein altes Beispiel, das ich irgendwo herumliegen hatte, aber ich hatte es eilig, als ich meine Antwort postete und den Kontext meines alten Beispiels nicht sorgfältig genug gelesen hatte.
Mein altes Beispiel beinhaltete ein Hauptformular, von dem Sie jede andere Form der Anwendung öffnen können. Das ist , wofür die Factory gedacht war, also müssen Sie nicht jedes andere Formular über die Konstruktorinjektion in das Hauptformular injizieren.
Stattdessen können Sie die Factory verwenden, um ein neues Formular zu öffnen:
Natürlich brauchen Sie die Factory nicht, nur um das Repository aus einem Formular zu holen, solange das Repository über die Konstruktorinjektion an das Formular übergeben wird.
Wenn Ihre App nur aus wenigen Formularen besteht, benötigen Sie die Factory überhaupt nicht. Sie können die Formulare auch einfach über die Konstruktorinjektion übergeben:
Tags und Links dependency-injection ninject service-locator testability thick-client