简体   繁体   中英

IoC/DI: How to inject specific instance when there are multiple implementations of same interface

Assume we have two implementations of IService interface:

public interface IService { }

public class Service1 : IService { }

public class Service2 : IService { }

Then we have two classes which are depended on IService :

public class Consumer1
{
    public Consumer1(IService svc) { }
}

public class Consumer2
{
    public Consumer2(IService svc) { }
}

Now, how can I inject Service1 into Consumer1 and Service2 into Consumer2 using Simple Injector as dependency container and without using a factory or separate interfaces?

The generic pattern (not related to specific DI container) of how to archive this would be also great :)

UPDATE
I've already tried the context based injection with Simple Injector. The documentation is very limited and I'm ended up with the following code:

container.RegisterConditional(
    typeof(IService),
    typeof(Service1),
    Lifestyle.Transient,
    c => c.Consumer.ImplementationType == typeof(Consumer1));

container.RegisterConditional(
    typeof(IService),
    typeof(Service2),
    Lifestyle.Transient,
    c => c.Consumer.ImplementationType == typeof(Consumer2));

container.Register<Consumer1>();
container.Register<Consumer2>();

but then I get an exception

The configuration is invalid. Creating the instance for type Consumer1 failed. The constructor of type Consumer1 contains the parameter with name 'svc' and type IService that is not registered. Please ensure IService is registered, or change the constructor of Consumer1. 1 conditional registration for IService exists that is applicable to IService, but its supplied predicate didn't return true when provided with the contextual information for Consumer1.

I've tried with different variations of predicate but without success...

c => c.Consumer.Target.TargetType == typeof(Consumer1)
c => c.Consumer.ServiceType == typeof(Consumer1)

I'm unable to reproduce this problem with the latest version (3.1) of SI. This test passes:

[Test]
public void Test1()
{
    var container = new Container();

    container.RegisterConditional<IService, Service1>(
        c => c.Consumer.ImplementationType == typeof(Consumer1));
    container.RegisterConditional<IService, Service2>(
        c => c.Consumer.ImplementationType == typeof(Consumer2));
    container.Register<Consumer1>();
    container.Register<Consumer2>();

    container.Verify();

    var result1 = container.GetInstance<Consumer1>();
    var result2 = container.GetInstance<Consumer2>();

    Assert.IsInstanceOf<Service1>(result1.Svc);
    Assert.IsInstanceOf<Service2>(result2.Svc);
}

What version of SI are you using and are you sure you are using the correct instance of the container ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM