我试图在开放注册中获取泛型参数类型而不必使用object。以下是代码段:
container.Register(typeof(IRepository<>),
() => new Repository<object>("connString"),
Lifestyle.Transient);
所以在lambda中我想用特定的泛型类型实例化存储库,而不是使用object。
答案 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,但这需要相当多的代码,所以这不是我通常会建议的。