我有一个像这样的查询处理程序:
public class FooQueryHandler : IQueryHandler<FooQuery, FooResult>
{
public FooResult Handle(FooQuery query) {
// Query handled here.
}
}
IQueryHandler
接口(interface)定义为:
public interface IQueryHandler<TQuery, Result> : where TQuery : IQuery
{
TResult Handle(TQuery query);
}
FooQuery
定义为:
public class FooQuery : IAuthorizedQuery
哪里IAuthorizedQuery
定义为:
public interface IAuthorizedQuery : IQuery
IQuery
只是简单的界面。 FooResult
只是一个简单的 DTO 对象。
IQueryHandler
使用简单注入(inject)器注入(inject)并在容器中注册为:
container.Register(typeof(IQueryHandler<,>), assemblies);
问题
我想装饰IQueryHandler
带有装饰器处理程序类。仅当查询对象(例如 FooQuery
)实现 IAuthorizedQuery
时,才应有条件地应用此装饰器。这样可以进行一些基于角色的授权。
如果查询没有实现IAuthorizedQuery
并且只有IQuery
那么就不应该进行任何装饰。
处理程序需要如下所示:
public AuthorizationQueryDecorator : IQueryHandler<TQuery, TResult>
where TQuery : IAuthorizedQuery
{
public AuthorizationQueryDecorator(
IQueryHandler<TQuery, TResult> handler,
IAuthorizer<TQuery> authorizer)
{
_authorizer = authorizer;
_handler = handler;
}
private readonly IAuthorizer<TQuery> _authorizer;
private readonly IQueryHandler<TQuery, TResult> handler;
public TResult Handle(TQuery query) {
if(!_authorizer.Authorise(query)) {
// throw exception
}
else {
handler.Handle(query);
}
}
}
IAuthorizer<TQuery>
接口(interface)只是一个带有 bool 方法的简单接口(interface) Authorise(TQuery query)
如果可以基于某些基于角色的逻辑执行查询,则返回 true。
问题是我不确定如何使用 SimpleInjector 有条件地注册装饰器。
条件本质上是 IQueryHandler
仅当 TQuery 对象实现 IAuthorizationQuery 时才应进行修饰。
我该怎么做?
目前我已经
container.RegisterDecorator(
typeof(IQueryHandler<,>),
typeof(AuthorizationQueryDecorator<,>), \\\ PREDICATE?);
但我不知道应该指定什么谓词?
编辑
看来我遇到的问题是 IAuthorizer
注册。
我有以下IAuthorizer
实现:
public FooQueryAuthorizer() : IAuthorizer<FooQuery>
和
public NullQueryAuthorizer<TQuery, TResult> : IQueryAuthorizer<TQuery, TResult>
where TQuery : IAuthorizedQuery<TResult> : IAuthorizer
SimpleInjector 注册IQueryAuthorizer
是:
container.RegisterConditional(
typeof(IQueryAuthorizer<,>),
typeof(NullQueryAuthorizer<,>),
c => !c.Handled);
但是,NullQueryAuthorizer
始终使用,无论是否存在特定实现(例如 FooQueryAuthorizer
)。
我该如何解决这个问题?
最佳答案
您无需执行任何操作;简单注入(inject)器将自动为您应用通用类型约束。所以您的注册很简单:
container.RegisterDecorator(
typeof(IQueryHandler<,>),
typeof(AuthorizationQueryDecorator<,>));
文档 describes :
Simple Injector will automatically apply the registered type conditionally based on it generic type constraints
关于c# - 使用SimpleInjector基于泛型参数条件注册装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38224530/