使用SimpleInjector

时间:2016-07-06 12:53:44

标签: c# .net simple-injector

我有一个像这样的查询处理程序:

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

我怎样才能解决这个问题?

1 个答案:

答案 0 :(得分:2)

你不需要做任何事情; Simple Injector将自动为您应用泛型类型约束。所以你的注册就是这样:

container.RegisterDecorator(
    typeof(IQueryHandler<,>),
    typeof(AuthorizationQueryDecorator<,>));

文档describes

  

Simple Injector将根据通用类型约束条件自动有条件地应用注册类型