Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject Multicasting

I want to bind multiple implementations of a service and have all of them called at once:

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 doesn't like that, and will throw an exception about having multiple bindings. Is there a way I can get around that error, and have all the implementations called?

Also, the Bind<> calls can be in different projects which may or may not be loaded at run-time, so creating a single implementation to call them won't work. This is part of a plug-in architecture for an ASP.NET MVC 3 web site.

like image 964
MikeWyatt Avatar asked Oct 31 '11 21:10

MikeWyatt


1 Answers

If you use constructor injection and have a List<IBreakfast> parameter, then Ninject will construct a list using all your bindings. You can then call Eat on these instances.

You can use this pattern to get Ninject to create a list of your plugins for instance.

    [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 { }

Output:

Eggs
Spam
MoreSpam

like image 74
Tim Lloyd Avatar answered Oct 20 '22 07:10

Tim Lloyd