ich "spiele" gerade mit DI per Unity bzw. MEF im Zusammenhang mit Repositories und UnitOfWork herum. Ich glaube, so langsam habe ich das Prinzip verstanden und hätte aber ganz gerne eine kurze abschließende Bestätigung über mein Verständnis einer bestimmten Verhaltensweise von DI-Containern.
Angenommen, ich hätte 2 Repositories A und B. Beiden Klassen wird im Konstrukture eine IUnitOfWork übergeben.
Nun habe ich z.B. in meinem ViewModel folgenden Code:
var a = IoC.Resolve(Of IRepositoryA)() var b = IoC.Resolve(Of IRepositoryB)()
In diesem Fall würde, je nach Konfiguration, die UnitOfWork u.U. 2 mal instanziiert, wenn es z.B. als Singleton konfiguriert ist. Oder auch nur ein einziges mal. Soweit klar für mich.
Wenn ich nun aber eine Constructor-Injection habe wie z.B.
Public Void Initialize(IRepositoryA repoA, IRepositoryB repoB) { }
dann hat es beim testen von Unity den Anschein auf mich, das nur eine Instanz der UnitOfWork erzeugt wird und beide Repositories dann dieselbe Instanz benutzen. Selbst, wenn ich es als Singleton konfiguriere.
Wäre für mich auch logisch, da ja beide im selben Konstruktor injiziert werden und ich das Verhalten (1 UOW oder 2 UOW) so beeinflussen kann. Ich finde allerdings in der Hilfe zu Unity nichts darüber und hätte ganz gerne von Euch bestätigt, das generell alle DI-Container auf diese Art und Weise arbeiten.
Hm, so einfach erscheint mir das nicht. Ich traue mir jedenfalls keine Aussage über "generell alle DI-Container" zu. Die beiden, mit denen ich praktische Erfahrung habe, sind Spring und LightCore. Bei Spring sind Singletons der Default, d.h. diese Objekte gibt es genau einmal. Bei LightCore sind Multitons der Standard. Wie sich der in dem Fall verhält, habe ich noch nicht ausprobiert, aber es wäre mir eigentlich egal - wenn ich mit Multitons arbeite und die Objekte auch noch vom DI-Container automatisch bereitgestellt werden, sollte Objektidentität keine große Rolle für den Code spielen.
Eine pauschale Antwort ist hier nicht möglich. Ich z.B. finde es alles andere als logisch, dass per DI die gleiche UnitOfWork von zwei verschiedenen Repositories genutzt wird. Thema: SOLID.
Bist du Dir wirklich sicher, dass die gleiche Instanz genutzt wird?
"Selbst, wenn ich es als Singleton konfiguriere"
Diese Aussage macht mich stutzig. Singleton bedeutet, dass nur eine Instanz vorhanden sein darf. Jede Anfrage an den Container oder über DI/PI gibt die gleiche Instanz wieder! Versteh mich bitte nicht falsch, aber vielleicht hast du da Factory mit Singleton vertauscht?
Ich habe es mal in C# und mit Autofac, welches meiner Meinung nach das beste Framework ist, nachgebildet.
Tests
[Test] public void TestUnitOfWorkIsSingleton() { var builder = new ContainerBuilder();
var repositoryA = container.Resolve<IRepositoryA>(); var repositoryB = container.Resolve<IRepositoryB>(); var repositoryLocator = container.Resolve<RepositoryLocator>();
var repositoryA = container.Resolve<IRepositoryA>(); var repositoryB = container.Resolve<IRepositoryB>(); var repositoryLocator = container.Resolve<RepositoryLocator>();
Das die Repositories bzw. die UnitOfWorks public sind, ist nur für die Tests. Normalerweise würde ich es anständig mocken, aber zur Veranschaulichung reicht es ja.
Test 1: - Die UnitOfWork wird als Singleton registriert. => Beide Repositories erhalten die gleiche Instanz.
Test 2: - Die UnitOfWork wird Factory registriert (Default bei Autofac, sofern man nichts anderes angibt) => Beide Repositories erhalten unterschiedliche Instanzen.
Edit: Da habe ich doch glatt mein Fazit vergessen ;) Jedes IoC Framework arbeitet ähnlich, jedoch nicht gleich. Daher ist eine pauschle Aussage nicht möglich, ich bezweifel allerdings sehr stark das Unity so funktioniert wie du es beschrieben hast.