2011-11-02 15 views
11

Używam programu Ninject 2.0 do obsługi DI w jednej z moich aplikacji i natknąłem się na coś, co mnie myli. Posiadanie zera dokumentacji nie pomaga zbytnio, aby być szczerym.Wstrzykiwanie wielu parametrów konstruktora tego samego typu za pomocą Ninject 2.0

Say Mam konstruktora z podpisem -

ctor(IServiceFactory factory1, IServiceFactory factory2) 
{ 
    this.factory1 = factory1; 
    this.factory2 = factory2; 
} 

Chociaż te dwie usługi wdrożenia tego samego interfejsu, są one dość różne implementacje i są stosowane w różnych porach więc nie chcę do wstrzykiwania IEnumerable<IServiceFactory> .

Moje pytanie brzmi: kiedy wiążę instancje, w jaki sposób mogę powiedzieć programowi Ninject, co należy wstrzykiwać dla każdego z nich?

Z góry dziękuję.

Aktualizacja

Dla wszystkich, którzy chcą zobaczyć kod skończy się po przeczytaniu linki Remo ... Tutaj jest to w skrócie. (Nigdy nie miał sobie sprawę C# atrybuty parametrów!)

//abstract factory 
public interface IServiceFactory 
{ 
    Service Create(); 
} 

//concrete factories 
public class Service1Factory : IServiceFactory 
{ 
    public IService Create() 
    { 
     return new Service1(); 
    } 
} 

public class Service2Factory : IServiceFactory 
{ 
    public IService Create() 
    { 
     return new Service2(); 
    } 
} 

//Binding Module (in composition root) 
public class ServiceFactoryModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IServiceFactory>() 
      .To<Service1Factory>() 
      .Named("Service1"); 

     Bind<IServiceFactory>() 
      .To<Service2Factory>() 
      .Named("Service2"); 
    } 
} 

//consumer of bindings 
public class Consumer(
    [Named("Service1")] service1Factory, 
    [Named("Service2")] service2Factory) 
{ 
} 

Odpowiedz

10

Przede wszystkim trzeba zadać sobie pytanie, czy za pomocą tego samego interfejsu jest poprawna, jeśli implementacje trzeba zrobić coś zupełnie innego. Zwykle interfejs jest umową między konsumentem a realizacją. Więc jeśli konsument oczekuje różnych rzeczy, możesz rozważyć zdefiniowanie różnych interfejsów.

Jeśli zdecydujesz się pozostać z tym samym interfejsem, niż musisz użyć powiązań warunkowych. Zobacz dokumentację na temat jak to zrobić:

https://github.com/ninject/ninject/wiki/Contextual-Binding

https://github.com/ninject/ninject/wiki/Conventions-Based-Binding

+0

Thanks Remo. W rzeczywistości są to różne implementacje abstrakcyjnej fabryki, które tworzą karty w interfejsie użytkownika, więc robią to samo, ... tylko z różnych powodów. – Stimul8d

+1

Myślę, że nie zrozumiałeś poprawnie. Z punktu widzenia konsumenta nie robią tego samego. Interfejs powinien być zdefiniowany z perspektywy konsumenta. Na przykład. jeśli masz interfejs fabryczny 'Fruit CreateFruit()' a konsument oczekuje dwóch implementacji dla bananów i jednego dla pomarańczy to powinieneś lepiej zdefiniować interfejs jako 'Banana CreateBanana()' i 'Pomarańczowy CreateOrange()' nawet jeśli potrzebujesz tylko jako owoce. –

+0

Rozumiem. Sugerujesz, że używam metod fabrycznych zamiast abstrakcyjnej fabryki z konkretnymi klasami fabrycznymi. Jest to opcja, ale same klasy fabryczne mają zależności (w tym przypadku pod-ekrany), które trzeba wstrzyknąć. Te zależności są łatwiejsze do rozwiązania za pomocą konkretnych fabryk i zastrzyków konstruktorów, niż w przypadku metod fabrycznych, czy nie są one czy też Ninject ma jakąś inną magię, której mi brakuje? – Stimul8d

Powiązane problemy