1

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)
5
  • The answer will always be specific to the DI framework you're using. You are asking about "context based injection", which, for SimpleInjector is documented here. As you're interested in other DI frameworks, Ninject does it like this. Commented Nov 27, 2015 at 15:35
  • Check this: simpleinjector.readthedocs.org/en/latest/… Commented Nov 27, 2015 at 15:36
  • Do you happen to have several interfaces with the same name IService? Commented Nov 27, 2015 at 21:03
  • "without using ... separate interfaces". Make sure that you aren't violation the Liskov Substitution Principle here, because if you do, the answer usually actually is* to create separate interfaces. Commented Nov 27, 2015 at 21:04
  • Note that the Consumer property of the PredicateContext describes the 'consuming class of the current dependency' (or parent), while the Consumer.Target describes the constructor parameter or property that the dependency is injected into. So Consumer.Target.TargetType will (almost) always be equal to the type of registration (in your case IService). Consumer.Target is more useful for getting the property or parameter name or can be used to query for certain attributes. Commented Nov 27, 2015 at 21:15

1 Answer 1

1

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?

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.