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