0

我正在处理一个问题。想象一下这个示例情况。我有一个模块,例如带有注入 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 书中被视为 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 容器的经验吗?您/哪个功能如何解决此问题?

4

2 回答 2

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 框架一起使用。

于 2014-09-08T17:53:28.590 回答
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 { }
于 2014-09-09T15:26:18.520 回答