依赖项注入-命名的依赖项
本文关键字:依赖 注入 | 更新日期: 2023-09-27 18:21:03
我正在处理一个问题。想象一下这个例子。我有一个模块,例如带有注入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;
}
}
我想定义哪个IUserRepository实现将在UserModule中使用。我想避免像Marc Seeman书中的IoC反模式那样的工厂模式,我只想通过容器配置来实现这一点。
我使用的是LightInject,它有一些类似于命名服务的东西,但它只能在顶级上使用。我需要这样的东西:
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中对此有什么建议吗
我在Lightinject中找到了一个特性注释,可以在其中注入适当类型的一些属性,但我不太喜欢这个解决方案。
您在其他IoC容器方面有经验吗?你/哪个功能可以解决这个问题
我必须同意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 { }
我知道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一起进行框架。