Tôi có cùng yêu cầu cho một dự án và triển khai một đường ống cụ thể nơi tôi có thể tiêm (nếu cần) một AuthorisationHandler cho một yêu cầu cụ thể. Điều này có nghĩa là tôi chỉ cần thêm một AuthorisationHandler mới cho mỗi lệnh mới mà tôi đã tạo, và sau đó nó sẽ được gọi trước khi yêu cầu xử lý lệnh thực tế.
Đường ống dẫn dầu:
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;
}
}
Các Authorsiation Handler:
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 My implemements IAuthorisationHandler mà trông như thế này:
public interface IAuthorisationHandler<in TRequest, TResponse> where TRequest : IAsyncRequest<TResponse>
{
Task<TResponse> Handle(TRequest request);
}
Nó sau đó ăn khớp với nhau bằng cách sử dụng DecorateAllWith (phần của structuremap)
cfg.For(typeof(IAsyncRequestHandler<,>)).DecorateAllWith(typeof(Pipeline<,>));
Không chắc chắn bạn nên làm điều này cho 3.x như thế này bây giờ có một giao diện đường ống mới
IPipelineBehavior<TRequest, TResponse>
Không sử dụng nó chưa nhưng tôi nghĩ rằng nó sẽ đơn giản hóa việc triển khai và có nghĩa là bạn có thể ngừng sử dụng Decorator Pattern DecorateAllWith.
Nhìn chung, tôi không hài lòng với bất kỳ giải pháp được đề xuất nào và đã kết thúc với giải pháp trước 3.0 của tôi. Ủy quyền phải được gắn với hành động được đề cập không phải là thông báo. – Betty