Ich verwende Microsoft Unity für die Abhängigkeitsinjektion und möchte Folgendes tun:
IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context
IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);
RepositoryA
und RepositoryB
beide haben einen Konstruktor, der einen IDataContext
Parameter akzeptiert, und ich möchte, dass Unity das Repository mit dem Kontext initialisiert, den ich übergebe. Beachten Sie auch, dass dies IDataContext
nicht bei Unity registriert ist (ich möchte keine 3 Instanzen von IDataContext
).
Foo(string name, int address) { ... }
container.Resolve<IFoo>(new ParameterOverrides { { "name", "bar" }, { "address", 42 } });
<2 Cent>
Was ist, wenn Sie sich später für einen anderen Dienst entscheiden, der mehr oder weniger als nur den Kontext erfordert?
Das Problem mit Konstruktorparametern und IoC besteht darin, dass die Parameter letztendlich an den verwendeten konkreten Typ gebunden sind und nicht Teil des Vertrags sind, den die Serviceschnittstelle definiert.
Mein Vorschlag wäre, dass Sie entweder auch den Kontext auflösen, und ich glaube, Unity sollte eine Möglichkeit für Sie haben, das Erstellen von 3 Instanzen davon zu vermeiden, oder Sie sollten einen Factory-Service in Betracht ziehen, der eine Möglichkeit für Sie bietet, das Objekt zu erstellen.
Was ist zum Beispiel, wenn Sie sich später dazu entschließen, ein Repository zu erstellen, das überhaupt nicht auf einer herkömmlichen Datenbank basiert, sondern stattdessen eine XML-Datei verwendet, um Dummy-Daten für den Test zu erstellen? Wie würden Sie den XML-Inhalt diesem Konstruktor zuführen?
IoC basiert auf dem Entkopplungscode. Indem Sie den Typ und die Semantik der Argumente mit den konkreten Typen verknüpfen, haben Sie die Entkopplung wirklich nicht richtig durchgeführt. Es besteht immer noch eine Abhängigkeit.
"Dieser Code kann möglicherweise mit jeder Art von Repository kommunizieren, solange er diese Schnittstelle implementiert ... Oh, und verwendet einen Datenkontext."
Jetzt weiß ich, dass andere IoC-Container dies unterstützen, und ich hatte es auch in meiner ersten eigenen Version, aber meiner Meinung nach gehört es nicht zum Auflösungsschritt.
</ 2 Cent>
quelle
Danke Jungs ... meins ähnelt dem Beitrag von "Exist". Siehe unten:
quelle
Sie können InjectionConstructor / InjectionProperty / InjectionMethod abhängig von Ihrer Injection-Architektur im ResolvedParameter <T> ("Name") verwenden, um eine Instanz eines vorregistrierten Objekts im Container abzurufen.
In Ihrem Fall muss dieses Objekt mit einem Namen registriert sein, und für dieselbe Versicherung benötigen Sie ContainerControlledLifeTimeManager () wie den LifeTimeManager.
quelle
Resolve
nimmt eine Sammlung vonResolverOverride
undInjectionConstructor
ist keineResolverOverride
.Die sehr kurze Antwort lautet: nein. Unity hat derzeit keine Möglichkeit, Parameter an den Konstruktor zu übergeben, die nicht konstant oder injiziert sind und die ich finden konnte. IMHO ist das die größte Sache, die es fehlt, aber ich denke, es ist eher beabsichtigt als ausgelassen.
Wie Jeff Fritz bemerkt, könnten Sie theoretisch einen benutzerdefinierten Lifetime-Manager erstellen, der weiß, welche Kontextinstanz in verschiedene Typen eingefügt werden soll. Dies ist jedoch eine Ebene der Hardcodierung, die den Zweck der Verwendung von Unity oder DI in erster Linie zu umgehen scheint.
Sie können einen kleinen Schritt von der vollständigen DI zurücktreten und Ihre Repository-Implementierungen für die Einrichtung ihrer eigenen Datenkontexte verantwortlich machen. Die Kontext - Instanz kann immer noch aus dem Behälter gelöst werden , aber die Logik für die Entscheidung , die man verwenden, um in die Umsetzung des Endlagers gehen würde. Es ist sicherlich nicht so rein, aber es würde das Problem beseitigen.
quelle
Eine andere Alternative, die Sie verwenden könnten (ich weiß nicht wirklich, ob es sich um eine bewährte Methode handelt oder nicht), besteht darin, zwei Container zu erstellen und für jeden eine Instanz zu registrieren:
hoffe das hilft auch
quelle
NotDan, ich denke, Sie haben möglicherweise Ihre eigene Frage in Kommentaren an lassevk beantwortet.
Zunächst würde ich einen LifetimeManager verwenden, um den Lebenszyklus und die Anzahl der von Unity erstellten IDataContext-Instanzen zu verwalten.
http://msdn.microsoft.com/en-us/library/cc440953.aspx
Es hört sich so an
ContainerControlledLifetimeManager
, als würde Ihnen das Objekt die Instanzverwaltung geben, die Sie benötigen. Mit diesem LifetimeManager sollte Unity allen Objekten, für die eine IDataContext-Abhängigkeit erforderlich ist, dieselbe Instanz des IDataContext hinzufügen.quelle