使用Simple Injector在Open Registration中获取通用参数类型

时间:2016-10-19 17:22:13

标签: c# generics dependency-injection simple-injector

我试图在开放注册中获取泛型参数类型而不必使用object。以下是代码段:

container.Register(typeof(IRepository<>),
    () => new Repository<object>("connString"),
    Lifestyle.Transient);

所以在lambda中我想用特定的泛型类型实例化存储库,而不是使用object。

1 个答案:

答案 0 :(得分:3)

接受lambda的Register的重载不支持泛型。原因是Simple Injector不再能够为您分析对象图并代表您进行任何分析。

有多种解决方案,但最简单的方法是将连接字符串参数提取到数据对象中,并让存储库依赖于此:

public class ConnectionStringSettings
{
    public readonly string ConnectionString;

    public ConnectionStringSettings(string connectionString) {
        this.ConnectionString = connectionString;
    }
}

container.RegisterSingleton(new ConnectionStringSettings("constr"));
container.Register(typeof(IRepository<>), typeof(Repository<>));

另一种选择是使用条件注册直接注册连接字符串:

container.RegisterConditional(typeof(string),
    Lifestyle.Singleton.CreateRegistration(typeof(string),
        () => "constr", container),
   c => c.Consumer.ImplementationType.Name == typeof(Repository<>).Name);

这样你可以保持构造函数参数不变。缺点是这种注册有点复杂,这种条件注册仅适用于像字符串这样的引用类型。我们可能会在第4节中fix

另一种选择是明确注册所有实现:

container.Register<IRepository<User>>(() => new Repository<User>("connString"));
container.Register<IRepository<Order>>(() => new Repository<Order>("connString"));
container.Register<IRepository<Asset>>(() => new Repository<Asset>("connString"));

另一种选择是使用未注册的类型解析:

container.ResolveUnregisteredType += (s, e) =>
{
    Type serviceType = e.UnregisteredServiceType;

    if (serviceType.IsGenericType && 
        serviceType.GetGenericTypeDefinition() == typeof(IRepository<>))
    {
        Type implementationType = typeof(Repository<>)
            .MakeGenericType(serviceType.GetGenericArguments()[0]);

        Registration r = Lifestyle.Transient.CreateRegistration(
            serviceType,
            () => Activator.CreateInstance(implementationType, "connectionString"),
            container);

        e.Register(r);
    }
};

另一种选择是override Simple Injector's default behavior when it comes to parameter injection,但这需要相当多的代码,所以这不是我通常会建议的。