我有一个像这样的查询处理程序:
public class FooQueryHandler : IQueryHandler<FooQuery, FooResult>
{
public FooResult Handle(FooQuery query) {
// Query handled here.
}
}
IQueryHandler
接口定义为:
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对象。
使用Simple Injector注入IQueryHandler
,并在容器中注册为:
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>
接口只是一个带有布尔方法Authorise(TQuery query)
的简单接口,如果可以根据某些基于角色的逻辑执行查询,则返回true。
问题是我不确定如何使用SimpleInjector有条件地注册装饰器。
条件基本上只有在TQuery对象实现IAuthorizationQuery时才应该装饰IQueryHandler
。
我该怎么做?
目前我有
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
IQueryAuthorizer
的SimpleInjector注册是:
container.RegisterConditional(
typeof(IQueryAuthorizer<,>),
typeof(NullQueryAuthorizer<,>),
c => !c.Handled);
但是,无论是否存在特定实施(例如NullQueryAuthorizer
),始终会使用FooQueryAuthorizer
。
我怎样才能解决这个问题?
答案 0 :(得分:2)
你不需要做任何事情; Simple Injector将自动为您应用泛型类型约束。所以你的注册就是这样:
container.RegisterDecorator(
typeof(IQueryHandler<,>),
typeof(AuthorizationQueryDecorator<,>));
文档describes:
Simple Injector将根据通用类型约束条件自动有条件地应用注册类型