我有以下界面:
public interface IQuery<TResult>
{
}
public interface IQueryHandler<in TQuery, out TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
我的一个实施查询是:
public class ApplyPermissionSetForUserAndPermissionTypeQuery<TQueryable, TEntity> : IQuery<TQueryable>
where TQueryable : IQueryable<TEntity>
{
}
和它的处理程序:
public class ApplyPermissionSetForUserAndPermissionTypeHandler<TQueryable, TEntity> : IQueryHandler<ApplyPermissionSetForUserAndPermissionTypeQuery<TQueryable, TEntity>, TQueryable>
where TQueryable : IQueryable<TEntity>
{
}
在构建我的容器时,我打电话:
container.Register(typeof(IQueryHandler<,>), container.Settings.QueryHandlerAssemblies);
哪个寄存器中的所有类型都已注册,并且已经适用于我的所有其他句柄。问题之一在于查询和处理程序本身包含泛型类型。
我目前在容器上注册了ResolveUnregisteredType事件,执行以下操作:
private void container_ResolveUnregisteredType(object sender, SimpleInjector.UnregisteredTypeEventArgs e)
{
var serviceType = e.UnregisteredServiceType;
if (serviceType.IsGenericType &&
serviceType.GetGenericTypeDefinition() == typeof(IQueryHandler<,>))
{
var queryArg = serviceType.GetGenericArguments()[0];
var resultArg = serviceType.GetGenericArguments()[1];
if (queryArg.IsGenericType &&
queryArg.GetGenericTypeDefinition() == typeof(ApplyPermissionSetForUserAndPermissionTypeQuery<,>))
{
var itemTypeArgument = queryArg.GetGenericArguments()[0];
var entityTypeArgument = queryArg.GetGenericArguments()[1];
if (itemTypeArgument != resultArg)
return;
Type typeToRegister;
try
{
typeToRegister = typeof(ApplyPermissionSetForUserAndPermissionTypeHandler<,>).MakeGenericType(itemTypeArgument, entityTypeArgument);
}
catch (ArgumentException)
{
// Thrown by MakeGenericType when the type constraints
// do not match. In this case, we don't have to register
// anything and can bail out.
return;
}
//Register a delegate which will return
e.Register(delegate () { return GetInstance(typeToRegister); });
}
}
}
这使它工作,所以我知道可以注册类型。这让我相信我错过了一些明显的东西,例如:该类型没有被&#34; container.Register(typeof(IQueryHandler&lt;,&gt;),container.Settings.QueryHandlerAssemblies)&#34;注册。方法
是否有可能使简单的注入器自动注册这种类型,并且我可以只注册程序集,因为我不会一直知道显式类型。例如。程序集列表可以是变量的,并且包含未知查询,因此我无法调用:
container.Register(typeof(IQueryHandler<,>), typeof(IQueryHandler<ApplyPermissionSetForUserAndPermissionTypeQuery<,>,>))
或者我是否必须自己枚举程序集以查找IQueryHandler&lt;,&gt;采用泛型类型并注册它们的类型,或者只是将我的事件处理程序更改为它的自我?
答案 0 :(得分:3)
Container.Register(Type, Assembly[])
方法不会自动注册通用注册,因为您经常希望以不同方式处理通用实现。例如,装饰器通常是通用的,需要以不同的方式处理。
由于您通常只有几个通用实现,因此可以按如下方式明确注册它们:
container.Register(typeof(IQueryHandler<,>), settings.QueryHandlerAssemblies);
container.Register(typeof(IQueryHandler<,>),
typeof(ApplyPermissionSetForUserAndPermissionTypeHandler<,>));
如果您有许多通用实现并且定期添加新的通用实现,您还可以通过首先调用Container.GetTypesToRegister
方法来包含泛型类型定义:
var queryHandlerTypes = container.GetTypesToRegister(typeof(IQueryHandler<,>),
settings.QueryHandlerAssemblies,
new TypesToRegisterOptions { IncludeGenericTypeDefinitions = true });
container.Register(typeof(IQueryHandler<,>),
queryHandlerTypes.Where(t => !t.IsGenericTypeDefinition));
foreach (Type type in queryHandlerTypes.Where(t => t.IsGenericTypeDefinition))
{
container.Register(typeof(IQueryHandler<,>), type);
}
请注意,这可能会在注册时直接失败,因为Simple Injector可能会检测到提供的开放泛型类型与先前进行的非泛型注册重叠。即使它在注册时没有失败,Simple Injector也可能在运行时(或在调用container.Verify()
期间)检测到重叠。这就是为什么这个Register
重载不接受开放泛型类型的批量注册的主要原因。如果您需要回退行为,请将注册更改为:
foreach (Type type in queryHandlerTypes.Where(t => t.IsGenericTypeDefinition))
{
container.RegisterConditional(typeof(IQueryHandler<,>), type, c => !c.Handled);
}