Как правильно вызывать обработчик команды/запроса из обработчика другой команды/запроса при использовании MediatR?
Нужно ли использовать такое:
private IMediator _mediator;
protected IMediator Mediator => _mediator ??= HttpContext.RequestServices.GetService<IMediator>();
и потом вызывать Mediator.Send(...)?
Или надо создавать экземпляр контроллера, в котором есть вызов нужной команды/запроса? Или вообще другое?
Ответы (1 шт):
Пусть у Вас есть примерно такой обработчик запроса. Он просто получает данные о продукте из БД
public class GetProductByIdQueryHandler: IRequestHandler<GetProductByIdQuery, Product>
{
private readonly CatalogDbContext _dbContext;
public GetProductByIdQueryHandler(CatalogDbContext dbContext) => _dbContext = dbContext;
public Task<Product> Handle(GetProductByIdQuery query, CancellationToken ct) =>
_dbContext.Products.SingleOrDefaultAsync(product => product.Id == query.Id, ct);
}
И есть обработчик команды AddProductToBasketCommand, который, добавляет товар в корзину, а для этого надо получить цену этого товара, логично применить для этого GetProductByIdQueryHandler, это делается так:
public class AddProductToBasketCommandHandler : IRequestHandler<AddProductToBasketCommand>
{
private readonly BasketDbContext _dbContext;
private readonly IMediator _mediator;
public AddProductToBasketCommandHandler(CatalogDbContext dbContext, IMediator mediator)
{
_dbContext = dbContext;
_mediator = mediator;
}
public async Task<Unit> Handle(AddProductToBasketCommand command, CancellationToken ct)
{
// Вот здесь зовём обработчика GetProductByIdQuery
var product = await _mediator.Send(new GetProductByIdQuery {Id = command.ProductId}, ct);
// Здесь делаем с этим продуктом что-то...
}
}
Вообще, и паттерн медиатор в целом и библиотека MediatR в частности о том, что компоненты вообще не знают друг о друге, то есть есть некий обработчик, который знает, как обработать запрос GetProductByIdQuery, есть другой, который знает, что делать с AddProductToBasketCommand, но друг о друге они не знают, а, если им надо воспользоваться услугами друг друга, то они просто говорят некоему посреднику: «Слушай, а найди там кого-нибудь, кто может обработать вот этот запрос/команду, пусть сделает, что надо и передаст через тебя результат», это позволяет создавать приложения с очень слабой связью между компонентами.
P.S. Контроллеры, о которых Вы упомянули, здесь совсем не при чём, вообще веб-фреймворк, которым пользуетесь надо расценивать, как нечто, что может авторизовать запрос и сериализовать/десериализовать данные, не более и создавать контроллеры руками точно не стоит.