2011-10-31 20 views
8

Chcę powiązać wiele implementacji usługi i mają wszystkie z nich nazywa się naraz:Ninject Multicasting

var kernel = new StandardKernel(); 

kernel.Bind<IBreakfast>.To<Spam>(); 
kernel.Bind<IBreakfast>.To<Eggs>(); 
kernel.Bind<IBreakfast>.To<MoreSpam>(); 

kernel.Get<IBreakfast>().Eat(); // call Eat method on all three bound implementations 

Ninject nie tak, i rzuci wyjątek o posiadające wiele powiązań. Czy istnieje sposób, w jaki można obejść ten błąd i wywołać wszystkie implementacje?

Ponadto wywołania mogą występować w różnych projektach, które mogą, ale nie muszą być ładowane w czasie wykonywania, więc utworzenie pojedynczej implementacji do ich wywołania nie będzie działać. Jest to część architektury wtyczki dla witryny sieci Web ASP.NET MVC 3.

Odpowiedz

12

Jeśli użyjesz wtrysku konstruktora i będziesz miał parametr List<IBreakfast>, wówczas Ninject skonstruuje listę używając wszystkich twoich powiązań. Następnie możesz wywołać Eat w tych instancjach.

Możesz użyć tego wzoru, aby uzyskać Ninject, aby utworzyć na przykład listę wtyczek.

[Test] 
    public void Test() 
    { 
     IKernel kernel = new StandardKernel(); 

     kernel.Bind<IBreakfast>().To<Eggs>(); 
     kernel.Bind<IBreakfast>().To<Spam>(); 
     kernel.Bind<IBreakfast>().To<MoreSpam>(); 

     var bling = kernel.Get<Bling>(); 
    } 

    private class Bling 
    { 
     public Bling(List<IBreakfast> things) 
     { 
      things.ForEach(t => t.Eat()); 
     } 
    } 

    private interface IBreakfast 
    { 
     void Eat(); 
    } 

    private class Ingrediant : IBreakfast 
    { 
     public void Eat(){Console.WriteLine(GetType().Name);} 
    } 

    private class Eggs : Ingrediant{} 
    private class Spam : Ingrediant{} 
    private class MoreSpam : Ingrediant { } 

wyjściowa:

Jaja
Spam
MoreSpam

+0

Postaram się to w godzinach porannych, kiedy dostać się do pracy, ale nie będzie Ninject wygeneruje błąd na drugim wywołaniu '<> (Bind). Do <>() '? – MikeWyatt

+5

@MikeWyatt: Nie, wiele "Bindów" jest w porządku. To, co nie jest w porządku, to "Get ", który daje więcej niż pojedynczy element. Jeśli chcesz to zrobić, możesz użyć 'GetAll ' (lub użyć niejawnego grupowania wielu rejestracji za pomocą 'List ', 'T []' lub 'IEnumerable ' zgodnie z sugestią) (I ludzie, którzy wysyłają/kodują ponieważ testy nigdy nie wysyłają rzeczy, które wybuchają!). Zauważ, że Ninject nie ma żadnego znaczenia do wygenerowania niejawnego Złożonego, aby rozsortować połączenia tak, jak chcesz. –

+1

To działa świetnie. Dzięki. – MikeWyatt

0

Nie można powiązać wiele konkretnych klas po jednym interfejsie, że wbrew zasadom DI.

Co właściwie chcesz zrobić, zainicjuj kilka konkretnych instancji i wywołaj ich metodę.

Możesz to sprawdzić:

Bind<IBreakfast>.To<Spam>().Named("Spam"); 
Bind<IBreakfast>.To<Eggs>().Named("Eggs"); 
Bind<IBreakfast>.To<MoreSpam>().Named("MoreSpam"); 

var breakfastList = new List() { "Spam", "Eggs", "MoreSpam" }; 
breakfastList.ForEach(item => kernel.Get<IBreakfast>(item).Eat()); 
+0

Nie powiedziałbym, że jest to niezgodne z zasadami DI. Jeśli twoja domena problemowa w naturalny sposób pasuje, zawsze istnieje potencjalna relacja jeden-do-wielu między interfejsem a konkretnymi klasami, to jest w porządku. Przyzwoite kontenery IoC umożliwiają modelowanie tego scenariusza. Scenariusz wtyczki OP jest jednym z tych typów modeli. –

+3

To podejście nie działa z architekturą wtyczek, ponieważ z definicji nie wiesz, jakie wtyczki będą obecne. – Bevan