Bind multiple implementations to the same interface with ninject
Asked Answered
R

3

21

Why is it not possible for me to do the following in Ninect?

Kernel.Bind<IPresenter>.To<DefaultPresenter>();
Kernel.Bind<IPresenter>.To<DashboardPresenter>();
Kernel.Bind<IPresenter>.To<HeartRatePresenter>();
Kernel.Bind<IPresenter>.To<GPSPresenter>();

Each of the 4 implementations have a different constructor that expect a different type. When i attempt this, Ninject throws an exception telling me that i cannot bind to the same interface more than once.

In a class called Presentable which all presenter classes inherit from, I am attempting to do Kernel.Get<IPresenter>(new ConstructorArgument("view", this)) so assign IPresentable Presenter within the page/view where the page/view implements an interface that the presenter expects as a parameter.

What is a way around this so that ninject recognises different constructor parameter types?

Reedy answered 22/1, 2014 at 15:52 Comment(0)
S
25

The binding to multiple interfaces is fine. Ninject allows this. see here: https://github.com/ninject/Ninject/wiki/Multi-injection

The problem is that Ninject can not just magically give you the "one" that you want depending on constructor arguments. What Ninject is designed to do with the code you wrote is to give you ALL of the bindings at once, when you ask for a List.

So like others said, if you only want a single instance, it sounds like what you want is contextual bindings. However, the way you asked your question and the other answers are a bit confusing, because it makes it sound like multi-injection is not possible, but it is possible, if it is really what you want. (which in this case it isn't)

Scarlatti answered 5/1, 2015 at 20:30 Comment(0)
B
15

You need to tell ninject how it should know which binding to choose.

Have a look at conditional binding: https://github.com/ninject/ninject/wiki/Contextual-Binding

I would recommend using the .When(...) syntax but maybe you prefer using .Named(...) (i.E. assigning a name/identifier to every binding and passing that name to ninject in the .Get<IPresenter>("SomeName") call).

Bulbul answered 23/1, 2014 at 9:10 Comment(2)
That help page is the shiznit! Very niceSantana
Bind if requesting class has a property name: Bind<IMessageService>().To<MailingService>().When(request => (((System.Reflection.PropertyInfo[])((System.Reflection.TypeInfo)((request.Target.Member).ReflectedType)).DeclaredProperties)[0]).Name.Contains("WhenHasSomePropertyName")); How do you use When(...) what is the best usage ?Benzel
P
5

You need to use contextual bindings. I usually use the concrete "target" class to decide which service implementation the kernel will provide by using .WhenInjectedInto() or .WhenInjectecExactlyInto().

Poynter answered 23/1, 2014 at 12:54 Comment(1)
Bind if target class has a property name: Bind<IMessageService>().To<MailingService>().When(request => (((System.Reflection.PropertyInfo[])((System.Reflection.TypeInfo)((request.Target.Member).ReflectedType)).DeclaredProperties)[0]).Name.Contains("WhenHasSomePropertyName")); How do you use When(...) what is the best usage can you show a example ?Benzel

© 2022 - 2024 — McMap. All rights reserved.