I know this has been discussed on multiple occasions before and I'm sorry to bring this up again but it is unclear to me what a best practice is to publish events/notifications from a handler. From what I have gathered it is not recommended to have nested handlers and send commands from within a handler and that makes perfect sense to me. Events/notifications on the other hand should be ok. What is the recommended way to go about this? The easiest would be to inject MediatR but that is also the least desired as it would also allow to send commands. Is there an easy way to just allow for publish? I have worked with NServiceBus before where this was available out of the box. Is there any reason why MediatR doesn't support the following scenario?
public async Task<int> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
// code to create user
var userId = 0;
Publish(new UserCreatedEvent { UserId = userId } );
return userId;
}
I believe it is not supported out of the box because there are not really any base handler classes (other than the helper classes to reduce complexity for synchronous processing). You could quite easily introduce your own base class for handlers that injects the mediator and stores it privately, only exposing the Publish Command.
public class HandlerBase<TRequest, TResponse> : IRequestHandler<TRequest, TResponse>
{
private readonly IMediator _mediator;
public HandlerBase(IMediator mediator)
{
_mediator = mediator;
}
protected Task Publish(INotification notification)
{
return _mediator.Publish(notification);
}
}
Another alternative would be to create a small wrapper for mediator that does something similar with an interface that only exposes the publish command.
And a third approach would be to introduce an IPublisher interface that the IMediator interface would extend from which contains the Publish methods. If this was baked into the core library then you could just inject IPublisher even though it would be the same instance of the mediator.
I think the last option might be worth a pull request, especially since it seems like it could be done in a non-breaking way thus not requiring a major version bump.
Most helpful comment
I believe it is not supported out of the box because there are not really any base handler classes (other than the helper classes to reduce complexity for synchronous processing). You could quite easily introduce your own base class for handlers that injects the mediator and stores it privately, only exposing the Publish Command.
Another alternative would be to create a small wrapper for mediator that does something similar with an interface that only exposes the publish command.
And a third approach would be to introduce an
IPublisherinterface that theIMediatorinterface would extend from which contains the Publish methods. If this was baked into the core library then you could just injectIPublishereven though it would be the same instance of the mediator.I think the last option might be worth a pull request, especially since it seems like it could be done in a non-breaking way thus not requiring a major version bump.