Can we have smoother usage in RequestHandlers as in MediatR?
MessagePipe is just wonderful. His performance is unmatched by competitors today. I used it in an experiment project of mine and the difference in load tests is noticeable.
The only thing that bothered me when I used it was the following: In a scenario of an application using CQRS, the code using MessagePipe is more coupled and repetitive than with MediatR.
I'll give an example: This is a gRPC service using MagicOnion + MessagePipe that I used in my studies:
namespace Cpnucleo.GRPC.Services;
[Authorize]
public class SistemaGrpcService : ServiceBase<ISistemaGrpcService>, ISistemaGrpcService
{
private readonly IAsyncRequestHandler<CreateSistemaCommand, CreateSistemaResponse> _createSistemaCommand;
private readonly IAsyncRequestHandler<ListSistemaQuery, ListSistemaResponse> _listSistemaQuery;
private readonly IAsyncRequestHandler<GetSistemaQuery, GetSistemaResponse> _getSistemaQuery;
private readonly IAsyncRequestHandler<RemoveSistemaCommand, RemoveSistemaResponse> _removeSistemaCommand;
private readonly IAsyncRequestHandler<UpdateSistemaCommand, UpdateSistemaResponse> _updateSistemaCommand;
public SistemaGrpcService(IAsyncRequestHandler<CreateSistemaCommand, CreateSistemaResponse> createSistemaCommand,
IAsyncRequestHandler<ListSistemaQuery, ListSistemaResponse> listSistemaQuery,
IAsyncRequestHandler<GetSistemaQuery, GetSistemaResponse> getSistemaQuery,
IAsyncRequestHandler<RemoveSistemaCommand, RemoveSistemaResponse> removeSistemaCommand,
IAsyncRequestHandler<UpdateSistemaCommand, UpdateSistemaResponse> updateSistemaCommand)
{
_createSistemaCommand = createSistemaCommand;
_listSistemaQuery = listSistemaQuery;
_getSistemaQuery = getSistemaQuery;
_removeSistemaCommand = removeSistemaCommand;
_updateSistemaCommand = updateSistemaCommand;
}
public async UnaryResult<OperationResult> AddAsync(CreateSistemaCommand command)
{
return await _createSistemaCommand.InvokeAsync(command);
}
public async UnaryResult<ListSistemaViewModel> AllAsync(ListSistemaQuery query)
{
return await _listSistemaQuery.InvokeAsync(query);
}
public async UnaryResult<GetSistemaViewModel> GetAsync(GetSistemaQuery query)
{
return await _getSistemaQuery.InvokeAsync(query);
}
public async UnaryResult<OperationResult> RemoveAsync(RemoveSistemaCommand command)
{
return await _removeSistemaCommand.InvokeAsync(command);
}
public async UnaryResult<OperationResult> UpdateAsync(UpdateSistemaCommand command)
{
return await _updateSistemaCommand.InvokeAsync(command);
}
}
It works very well, as expected. The only issue in this implementation focused on CQRS is that the modules need to be unique for each request (Commands/Queries and their responses) end up making the implementation very repetitive and verbose.
This is the same gRPC service using MagicOnion + MediatR:
namespace Cpnucleo.GRPC.Services;
[Authorize]
public class SistemaGrpcService : ServiceBase<ISistemaGrpcService>, ISistemaGrpcService
{
private readonly IMediator _mediator;
public SistemaGrpcService(IMediator mediator)
{
_mediator = mediator;
}
public async UnaryResult<OperationResult> AddAsync(CreateSistemaCommand command)
{
return await _mediator.Send(command);
}
public async UnaryResult<ListSistemaViewModel> AllAsync(ListSistemaQuery query)
{
return await _mediator.Send(query);
}
public async UnaryResult<GetSistemaViewModel> GetAsync(GetSistemaQuery query)
{
return await _mediator.Send(query);
}
public async UnaryResult<OperationResult> RemoveAsync(RemoveSistemaCommand command)
{
return await _mediator.Send(command);
}
public async UnaryResult<OperationResult> UpdateAsync(UpdateSistemaCommand command)
{
return await _mediator.Send(command);
}
}
Wouldn't it be possible to have a RequestHandler in MagicOnion that works similarly to how MediatR works for cases like the one I mentioned above?
good question.