I seem to be stumped on how to implemented the strategy pattern with a DI container.
I have a strategy interface:
public interface IUserCompaniesInviteStrategy
{
bool InviteUserToCompany(UserCompaniesInviteRequest userCompaniesInviteRequest);
}
and a couple of concrete classes:
public class ConcreteExistingUserInviteStrategy : IUserCompaniesInviteStrategy
public class ConcreteNewUserInviteStrategy : IUserCompaniesInviteStrategy
How do I wire up Unity with this?
container.RegisterType<IUserCompaniesInviteStrategy, ConcreteExistingUserInviteStrategy>();
container.RegisterType<IUserCompaniesInviteStrategy, ConcreteNewUserInviteStrategy>();
obviously doesn't work...
I tried:
container.RegisterType<IUserCompaniesInviteStrategy<ConcreteExistingUserInviteStrategy>, ConcreteExistingUserInviteStrategy>();
container.RegisterType<IUserCompaniesInviteStrategy<ConcreteNewUserInviteStrategy>, ConcreteNewUserInviteStrategy>();
with
public interface IUserCompaniesInviteStrategy<T>
That doesn't seem to work.
I think what I'd like to do here is use named types, so like:
container.RegisterType<IUserCompaniesInviteStrategy, ConcreteExistingUserInviteStrategy>("1");
container.RegisterType<IUserCompaniesInviteStrategy, ConcreteNewUserInviteStrategy>("2");
However, I have constructor injection setup and using container.resolve isn't a good option for me because of n-tier architecture and chaining dependencies I'd have to resolve.
How can I inject a named type into a constructor? Is there a better way to do what I'm trying to do? (Create an interface that resolves to two concrete strategies)
Update:
I took a look at With Unity how do I inject a named dependency into a constructor? . The accepted answer won't work because I don't have a dependency on Unity in my domain, nor do I want it. I tried the StrategyResolver, but I'm getting:
An error occurred when trying to create a controller of type 'UserController'. Make sure that the controller has a parameterless public constructor.
That is indicative of a DI problem.
The StrategyResolver and IStrategyResolver are the same as in the example:
public class StrategyResolver : IStrategyResolver
{
private IUnityContainer container;
public StrategyResolver(IUnityContainer unityContainer)
{
this.container = unityContainer;
}
public T Resolve<T>(string namedStrategy)
{
return this.container.Resolve<T>(namedStrategy);
}
}
public interface IStrategyResolver
{
T Resolve<T>(string namedStrategy);
}
My config:
container.RegisterType<IUserCompaniesInviteStrategy, ConcreteExistingUserInviteStrategy>("ExistingUser");
container.RegisterType<IUserCompaniesInviteStrategy, ConcreteNewUserInviteStrategy>("NewUser");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<IUserFactory, UserFactory>();
Concretes:
public class ConcreteExistingUserInviteStrategy : IUserCompaniesInviteStrategy
public class ConcreteNewUserInviteStrategy : IUserCompaniesInviteStrategy
And then I call it like:
_strategyResolver.Resolve<IUserCompaniesInviteStrategy>("ExistingUser");
Not sure what's wrong with it.