使用简单注入器基于泛型参数的装饰器的条件注册
本文关键字:参数 注册 条件 泛型 注入器 简单 于泛型 | 更新日期: 2023-09-27 17:55:29
我有一个这样的查询处理程序:
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 对象。
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。
问题是我不确定如何有条件地使用 SimpleJector 注册装饰器。
该条件实质上是,仅当 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
的简单注射器注册是:
container.RegisterConditional(
typeof(IQueryAuthorizer<,>),
typeof(NullQueryAuthorizer<,>),
c => !c.Handled);
但是,始终使用NullQueryAuthorizer
,无论特定实现(例如 FooQueryAuthorizer
) 存在。
我怎样才能解决这个问题?
你不需要做任何事情;简单注入器将自动为您应用泛型类型约束。所以你的注册很简单:
container.RegisterDecorator(
typeof(IQueryHandler<,>),
typeof(AuthorizationQueryDecorator<,>));
该文档描述了:
简单注入器将根据泛型类型约束有条件地自动应用注册类型