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)
IService
? - StevenConsumer
property of thePredicateContext
describes the 'consuming class of the current dependency' (or parent), while theConsumer.Target
describes the constructor parameter or property that the dependency is injected into. SoConsumer.Target.TargetType
will (almost) always be equal to the type of registration (in your caseIService
).Consumer.Target
is more useful for getting the property or parameter name or can be used to query for certain attributes. - Steven