简体   繁体   English

使用简单注入器在开放式注册中获取通用参数类型

[英]Get Generic Argument Type in Open Registration with Simple Injector

I am attempting to get the generic argument type in an open registration without having to use object. 我试图在开放式注册中获取通用参数类型,而不必使用对象。 Here is the code snippet: 这是代码片段:

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

So in the lambda I would like to instantiate the repository with the specific generic type instead of using object. 因此,在lambda中,我想使用特定的通用类型实例化存储库,而不是使用对象。

The overloads of Register that take in a lambda don't support generics. 接收lambda的Register重载不支持泛型。 The reason for this is that Simple Injector wouldn't be able to analyse the object graph for you anymore and do any analysis on your behalf. 这样做的原因是,Simple Injector将不再能够为您分析对象图并不能代表您执行任何分析。

There are multiple solutions, but what is probably the simplest is to extract the connection string parameter into a data object, and let the repository depend on that: 有多种解决方案,但最简单的方法可能是将连接字符串参数提取到数据对象中,然后让存储库依赖于此:

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<>));

Another option is to register the connection string directly using conditional registration: 另一种选择是使用条件注册直接注册连接字符串:

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

This way you can leave the constructor argument as is. 这样,您可以将构造函数参数保留为原样。 Downside is that this registration is somewhat more complex and this conditional registration only works with reference types like strings. 缺点是此注册稍微复杂一些,并且此条件注册仅适用于字符串等引用类型。 We might fix this in v4. 我们可能会在v4中解决此问题。

Another option is to register all implementations explicitly: 另一个选择是显式注册所有实现:

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

Another option is to use unregistered type resolution: 另一种选择是使用未注册的类型解析:

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);
    }
};

Yet another option is to override Simple Injector's default behavior when it comes to parameter injection , but this requires quite a lot of code, so this is not something I would typically advise. 还有一种选择是在涉及参数注入时覆盖Simple Injector的默认行为 ,但这需要大量代码,因此我通常不建议这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM