Injecting multiple constructor parameters of the same type with Ninject 2.0
Asked Answered
S

1

11

I'm using Ninject 2.0 to handle DI in one of my apps and I've come across something that's confusing me. Having zero documentation doesn't help too much either to be honest.

Say I have a constructor with the signature -

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

Although these two services implement the same interface, they are quite different implementations and are used at different times so I don't want to inject an IEnumerable<IServiceFactory>.

My question is, when I'm binding the instances, how do I tell Ninject what to inject for each?

Thanks in advance.

Update

For the sake of anyone wanting to see the code would end up after reading Remo's links,...Here it is in brief. (I never realised C# had parameter attributes!)

//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)
{
}
Skit answered 2/11, 2011 at 15:26 Comment(0)
L
10

First of all you have to ask yourself if using the same interface is correct if the implementations need to do a completely different thing. Normally, the interface is the contract between the consumer and the implementation. So if the consumer expects different things then you might consider to define different interfaces.

If you decide to stay with the same interface than you have to use conditional bindings. See the documentation about how this is done:

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

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

Lorrianelorrie answered 2/11, 2011 at 16:15 Comment(3)
Thanks Remo. They're actually different implementations of an abstract factory which create Tabs in the UI so they do the same thing,...just for different reasons.Skit
I think you didn't understand correctly. From point of the consumer they do not the same thing. The interface should be defined from the perspective of the consumer. E.g. if you have a factory interface Fruit CreateFruit() and the consumer expects two implementations one for bananas and one for oranges then you should better define the interface as Banana CreateBanana() and Orange CreateOrange() even if you need them only as fruits.Lorrianelorrie
I see. You're suggesting that I use factory methods rather than an abstract factory with concrete factory classes. It's an option but the factory classes themselves have dependencies (sub-screens in this case) which need to be injected. Those dependencies are much easier to resolve with concrete factories and constructor injection rather than factory methods aren't they or does Ninject have some other magic I'm missing?Skit

© 2022 - 2024 — McMap. All rights reserved.