2015-01-03 17 views
7

Powiedzmy, że mam dwa kontrolery: ControllerA i ControllerB. Oba te kontrolery przyjmują jako parametr IFooInterface. Teraz mam 2 implementacje IFooInterface, FooA i FooB. Chcę wprowadzić FooA w ControllerA i FooB w ControllerB. Można to łatwo osiągnąć w programie Ninject, ale przechodzę do prostego wtryskiwacza ze względu na lepszą wydajność. Jak mogę to zrobić w Simple Injector? Należy pamiętać, że ControllerA i ControllerB znajdują się w różnych zespołach i są ładowane dynamicznie.Wstrzykiwanie warunkowe Simple Injector

Dzięki

+2

To pytanie ma pochodzić kilka razy na Stackoverflow, a to jest mój obowiązek kwestionowania takiego projektu. Chociaż taki projekt nie zawsze jest zły, należy uważać, aby nie naruszać zasady Liskov Substitution Principle. Pytanie brzmi: czy ControllerA nadal działa, gdy jest wstrzykiwany FooB, czy też ma przerwy? Jeśli się zepsuje, naruszasz LSP, co oznacza, że ​​FooA i FooB powinny implementować inny interfejs. – Steven

+0

@Thanks thanks, dałeś mi coś do myślenia :) – Davita

+0

@ Jeszcze jedna myśl, ControllerA nadal będzie działać po wstrzyknięciu FooB, z tej perspektywy, w zasadzie mogę skrócić ilość kontrolerów. Problem polega na tym, że kontroler przesyła IFooInterface z niektórymi danymi z bazy danych, która jest inna dla FooA i FooB, więc powinna wiedzieć, które dane wybrać z bazy danych. – Davita

Odpowiedz

5

Dokumentacja SimpleInjector nazywa to context-based injection. Od wersji 3 można użyć RegisterConditional. Począwszy od wersji 2.8, ta funkcja nie jest zaimplementowana w SimpleInjector, jednak dokumentacja zawiera a working code sample implementing this feature jako rozszerzenie klasy Container.

Stosując te metody rozszerzeń byś zrobił coś takiego:

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

Od wersji 3 Proste Injector ma metodę RegisterConditional

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 naprawdę przydatne! –