我现在正在做以下事情
container.Register<IDatabaseMapper<User>, DatabaseMapper<User, OracleException>>();
container.Register<IDatabaseMapper<Desk>, DatabaseMapper<Desk, OracleException>>();
container.Register<IDatabaseMapper<Commodity>, DatabaseMapper<Commodity, OracleException>>();
但我想做这样的事情
container.RegisterOpenGeneric(typeof(IDatabaseMapper<>), typeof(DatabaseMapper<,OracleException>));
这有可能吗?
答案 0 :(得分:2)
这可能吗?是和否: - )
typeof(DatabaseMapper<,OracleException>)
不是有效的C#代码。您要么必须提供所有泛型类型参数,要么根本不提供。因此,无法通知Container
它应使用TException
填写缺少的OracleException
类型参数。所以不,你不能这样做。
但是,当然你可以这样做:-)。只需创建一个继承自OracleExceptionDatabaseMapper<T>
的{{1}}类,并在注册中使用该类型:
DatabaseMapper<T, OracleException>
这样,给定的实现只有一个泛型类型,可以映射到给定服务接口的单个泛型类型参数。
<强>更新强>
由于Simple Injector 2.4可以注册parial open泛型类型,但由于C#仍然不支持,你必须手动创建部分开放泛型类型,如下所示:
// Helper class
public class OracleExceptionDatabaseMapper<T>
: DatabaseMapper<T, OracleException>
{
}
// Registration
container.RegisterOpenGeneric(typeof(IDatabaseMapper<>),
typeof(OracleExceptionDatabaseMapper<>));
答案 1 :(得分:1)
为了完整性,以下是使用未注册的类型解析如何执行此操作的示例:
container.ResolveUnregisteredType += (s, e) =>
{
var serviceType = e.UnregisteredServiceType;
if (serviceType.IsGenericType &&
serviceType.GetGenericTypeDefinition() == typeof(IDatabaseMapper<>))
{
Type argument = serviceType.GetGenericArguments()[0];
var closedDatabaseMapperType = typeof(DatabaseMapper<,>)
.MakeGenericType(argument, typeof(OracleException));
var registration =
container.GetRegistration(closedDatabaseMapperType, true);
e.Register(registration.BuildExpression());
}
};
只要请求未注册的类型,容器就会调用ResolveUnregisteredType
事件。这为您提供了注册该类型的最后机会。提供的UnregisteredTypeEventArgs
包含两个Register
方法重载,允许您注册该类型(使用Func<T>
或使用Expression
)。
上面的代码检查所请求的服务类型是否为IDatabaseMapper<T>
,如果是,它将构造DatabaseMapper<T, OracleExpression>
,其中T
被替换为服务类型的实际类型。使用该类型,从容器请求该类型的注册。使用该注册对象的BuildExpression
方法,我们可以构建一个表达式树,用于描述DatabaseMapper
的新实例的创建。此表达式ID使用e.Register
方法进行注册,该方法有效地将IDatabaseMapper<T>
映射到DatabaseMapper<T, OracleException>
的创建。
重要提示:我认为使用未注册的类型解析应仅用作后备选项,因为通常有更简单的方法来解决您的问题(例如我在其他答案中显示的方法),但未注册的类型解析可能很有用在某些高级场景中(例如,当DatabaseMapper<T, TException>
被密封时)。