2016-07-06 2 views
2

У меня есть обработчик запроса, как это:Условная регистрация Decorator на основе родового параметра с помощью SimpleInjector

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), который возвращает истину, если запрос может быть выполнен на основе некоторой ролевой логики.

Проблема в том, что я не уверен, как условно зарегистрировать декоратор с помощью SimpleInjector.

Условие состоит в том, что IQueryHandler должен быть только украшен, если объект TQuery реализует IAuthorizationQuery.

Как это сделать?

На данный момент у меня

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

, но я не знаю, что должно быть указано Predicate?

EDIT

Это выглядит так, как будто этот вопрос я имею с 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) есть.

Как я могу обойти это?

+0

Если вы сделаете 'IQuery' общий тип, содержащий возвращаемый тип (то есть 'IQuery '), это дает вам много дополнительных метаданных для запроса, и дает вам поддержку времени компиляции и препятствует вам приложению (и узнайте во время выполнения t вы используете неправильный запрос). [Эта статья] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=92) описывает эту модель, используя общий «IQuery ». – Steven

+0

Спасибо Стивену - на практике это так, я просто удалил параметр на вопрос, чтобы сделать его немного яснее. – Graham

+0

Как регистрируется 'FooQueryAuthorizer'? – Steven

ответ

2

Вам не нужно ничего делать; Простой инжектор автоматически применит для вас типовые ограничения типа. Так что ваша регистрация просто:

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

Документация describes:

Simple Инжектор автоматически применит зарегистрированный тип условно на его основе общих ограничений типа

+0

Спасибо Стивен - с момента публикации, я думаю, что проблема, с которой я столкнулась, фактически связана с регистрацией 'IQueryAuthorizer'. Я обновил вопрос. – Graham

Смежные вопросы