我正在处理一个问题。想象一下这个例子的情况。我有一个模块,例如注入了IUserRepository的UserModule。 IUserRepository可以有更多的实现,例如IUserRepositorySql和IUserRepositoryDefault。
public class UserModule : IUserModule
{
private readonly IUserRepository userRepository;
public UserModule(IUserRepository userRepository)
{
if (userRepository == null) throw new ArgumentNullException("userRepository");
this.userRepository = userRepository;
}
}
我想定义在UserModule中将使用哪个IUserRepository实现。我想避免在Marc Seeman book中被视为IoC反模式的工厂模式,我想只在容器配置中实现这一点。
我正在使用LightInject,它有类似named services的东西,但它只能在顶层使用。我需要这样的东西:
var container = new ServiceContainer();
container.Register<IUserRepository, UserRepositorySql>("Sql");
container.Register<IUserRepository, UserRepositoryDefault>("Default");
container.Register<IUserModule, UserModule>();
var instance = container.GetInstance<IUserModule>("Sql");
此代码应返回带有注入UserRepositorySql实例的IUserModule实例,但当然不会。
请问你在LightInject中有这个问题吗?
我找到了一个功能annotation in Lightinject,我可以在其中注入一些适当类型的属性,但我不太喜欢这个解决方案。
您对其他一些IoC容器有经验吗?您如何/哪个功能可以解决此问题?
答案 0 :(得分:1)
我知道Unity支持指定在执行时使用哪个命名实例 构造函数注入通过ResolvedParameter类(它只是工作 像你想象中的建筑一样):
container.Register<IUserModule, UserModule>(
new InjectionConstructor(
new ResolvedParameter<IUserModule>("Sql")));
但是,大多数DI框架也支持工厂方法,以及上面的例子 也可以用Unity编写:
container.Register<IUserModule>(
new InjectionFactory(cont => cont.Resolve<IUserModule>("Sql"));
在这种情况下,您告诉Unity您希望它随时使用您的表达式 它应该创建一个IUserModule实例,在那个表达式中,你是免费的 使用容器来解析特定实例。
我怀疑你的DI可以很好地实现后一种结构 框架也是如此。
答案 1 :(得分:1)
我必须同意Steven和Astrotrain,但还有第三种选择。
以下示例使用参数来解析IUserRepository接口的正确实现。
using LightInject;
class Program
{
static void Main(string[] args)
{
var container = new ServiceContainer();
container.Register<IUserRepository, UserRepositorySql>("Sql");
container.Register<IUserRepository, UserRepositoryDefault>("Default");
container.Register<string, IUserModule>(
(factory, serviceName) => new UserModule(factory.GetInstance<IUserRepository>(serviceName)));
var userModuleWithSqlRepository = container.GetInstance<string, IUserModule>("Sql");
var userModuleWithDefaultRepository = container.GetInstance<string, IUserModule>("Default");
}
}
public interface IUserModule { }
public class UserModule : IUserModule
{
public UserModule(IUserRepository repository)
{
}
}
public interface IUserRepository { }
public class UserRepositorySql : IUserRepository { }
public class UserRepositoryDefault : IUserRepository { }