使用简单注入器基于泛型参数的装饰器的条件注册

本文关键字:参数 注册 条件 泛型 注入器 简单 于泛型 | 更新日期: 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<,>));

该文档描述了:

简单注入器将根据泛型类型约束有条件地自动应用注册类型