我对一个项目有相同的要求,并实现了一个特定的管道,我可以在其中为特定请求注入(如果需要)一个 AuthorisationHandler。这意味着我只需要为我创建的每个新命令添加一个新的 AuthorisationHandler,然后在请求处理实际命令之前调用它。
管道:
public class Pipeline<TRequest, TResponse> : IAsyncRequestHandler<TRequest, TResponse> where TRequest : IAsyncRequest<TResponse>
{
private readonly IAuthorisationHandler<TRequest, TResponse>[] _authorisationHandlers;
private readonly IAsyncRequestHandler<TRequest, TResponse> _inner;
private readonly IPostRequestHandler<TRequest, TResponse>[] _postHandlers;
public Pipeline(IAuthorisationHandler<TRequest, TResponse>[] authorisationHandlers, IAsyncRequestHandler<TRequest, TResponse> inner, IPostRequestHandler<TRequest, TResponse>[] postHandlers)
{
_authorisationHandlers = authorisationHandlers;
_inner = inner;
_postHandlers = postHandlers;
}
public async Task<TResponse> Handle(TRequest message)
{
foreach (var authorisationHandler in _authorisationHandlers)
{
var result = (ICommandResult)await authorisationHandler.Handle(message);
if (result.IsFailure)
{
return (TResponse)result;
}
}
var response = await _inner.Handle(message);
foreach (var postHandler in _postHandlers)
{
postHandler.Handle(message, response);
}
return response;
}
}
授权处理程序:
public class DeleteTodoAuthorisationHandler : IAuthorisationHandler<DeleteTodoCommand, ICommandResult>
{
private IMediator _mediator;
private IAuthorizationService _authorisationService;
private IHttpContextAccessor _httpContextAccessor;
public DeleteTodoAuthorisationHandler(IMediator mediator, IAuthorizationService authorisationService, IHttpContextAccessor httpContextAccessor)
{
_mediator = mediator;
_authorisationService = authorisationService;
_httpContextAccessor = httpContextAccessor;
}
public async Task<ICommandResult> Handle(DeleteTodoCommand request)
{
if (await _authorisationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, "DeleteTodo"))
{
return new SuccessResult();
}
var message = "You do not have permission to delete a todo";
_mediator.Publish(new AuthorisationFailure(message));
return new FailureResult(message);
}
}
我的 AuthorisationHandler 实现了 IAuthorisationHandler,如下所示:
public interface IAuthorisationHandler<in TRequest, TResponse> where TRequest : IAsyncRequest<TResponse>
{
Task<TResponse> Handle(TRequest request);
}
然后它使用 DecorateAllWith (结构图的一部分)挂在一起
cfg.For(typeof(IAsyncRequestHandler<,>)).DecorateAllWith(typeof(Pipeline<,>));
不确定您是否应该为 3.x 执行此操作,因为它现在有一个新的管道接口
IPipelineBehavior<TRequest, TResponse>
尚未使用它,但我认为它会简化实现,并且意味着您可以停止使用装饰器模式 DecorateAllWith。