依赖注入 - 命名依赖项

时间:2014-09-08 17:22:12

标签: c# .net dependency-injection light-inject

我正在处理一个问题。想象一下这个例子的情况。我有一个模块,例如注入了IUserRepository的UserModule。 IUserRepository可以有更多的实现,例如IUserRepositorySql和IUserRepositoryDe​​fault。

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容器有经验吗?您如何/哪个功能可以解决此问题?

2 个答案:

答案 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 { }