2015-01-03 5 views
7

Sagen wir, ich habe zwei Controller: ControllerA und ControllerB. Beide Controller akzeptieren als Parameter IFooInterface. Jetzt habe ich 2 Implementierungen von IFooInterface, FooA und FooB. Ich möchte FooA in ControllerA und FooB in ControllerB injizieren. Dies wurde in Ninject leicht erreicht, aber ich bewege mich aufgrund der besseren Leistung zum Simple Injector. Wie kann ich das in Simple Injector tun? Beachten Sie, dass sich ControllerA und ControllerB in verschiedenen Assemblies befinden und dynamisch geladen werden.Einfache Einspritzung bedingte Einspritzung

Dank

+2

RegisterConditional Methode hat diese Frage mehrmals auf Stackoverflow kommen, und es ist mein Pflicht, dieses Design in Frage zu stellen. Obwohl ein solches Design nicht immer falsch ist, müssen Sie vorsichtig sein, das Liskov Substitutionsprinzip nicht zu verletzen. Die Frage ist also: Funktioniert ControllerA noch, wenn es mit FooB injiziert wird, oder bricht es? Wenn es bricht, verletzen Sie LSP und das bedeutet, dass FooA und FooB jeweils eine andere Schnittstelle implementieren sollten. – Steven

+0

@Steven danke, du hast mir etwas zum denken gegeben :) – Davita

+0

@Steven noch ein Gedanke, der ControllerA wird immer noch funktionieren, wenn FooB injiziert wird, aus dieser Perspektive kann ich prinzipiell die Anzahl der Controller verkürzen. Das Problem ist, dass der Controller IFooInterface mit einigen Daten aus der Datenbank versorgt, die für FooA und FooB unterschiedlich sind. Daher sollte er wissen, welche Daten aus der Datenbank ausgewählt werden sollen. – Davita

Antwort

5

Die SimpleInjector Dokumentation nennt dies context-based injection. Ab Version 3 würden Sie RegisterConditional verwenden. Ab Version 2.8 ist diese Funktion nicht in SimpleInjector implementiert, die Dokumentation enthält jedoch a working code sample implementing this feature als Erweiterungen der Klasse Container.

diese Erweiterungen Methoden verwenden würden Sie so etwas tun:

Type fooAType = Assembly.LoadFrom(@"path\to\fooA.dll").GetType("FooA"); 
Type fooBType = Assembly.LoadFrom(@"path\to\fooB.dll").GetType("FooB"); 
container.RegisterWithContext<IFooInterface>(context => { 
    if (context.ImplementationType.Name == "ControllerA") 
    { 
     return container.GetInstance(fooAType); 
    } 
    else if (context.ImplementationType.Name == "ControllerB") 
    { 
     return container.GetInstance(fooBType) 
    } 
    else 
    { 
     return null; 
    } 
}); 
12

Seit Version 3 einfache Injector

container.RegisterConditional<IFooInterface, FooA>(c => c.Consumer.ImplementationType == typeof(ControllerA)); 
container.RegisterConditional<IFooInterface, FooB>(c => c.Consumer.ImplementationType == typeof(ControllerB)); 
container.RegisterConditional<IFooInterface, DefaultFoo>(c => !c.Handled); 
+0

Mate wirklich nützlich! –