Mediatr: Using Mediator Pipeline without a message abstraction (Call Handler via mediator directly)

Created on 5 Jun 2019  路  1Comment  路  Source: jbogard/MediatR

I would like to be able to "Execute" a handler with it's pipeline without having the abstraction between a Request and it's handler.

I've seen that in a lot of cases the abstraction between a handler and a request only gives friction (go to implementation). So I would like to propose a way to "Execute" a handler via Mediator for the Pipeline.

Something like:

var pingHandler = new PingHandler(output);
var response = await mediator.Execute(pingHandler.Handle, new Ping { Message = "Ping" });

With the following interface.

public delegate Task<TResponse> RequestHandlerHandleDelegate<TRequest, TResponse>(
        TRequest request, CancellationToken cancellation = default)
        where TRequest : IRequest<TResponse>;

public interface IMediator
{
        Task<TResponse> Execute<TRequest, TResponse>(
            RequestHandlerHandleDelegate<TRequest, TResponse> handler,
            TRequest request,
            CancellationToken cancellationToken = default)
            where TRequest : IRequest<TResponse>;
...
// In the RequestHandlerWrapper something like:
public Task<TResponse> HandleWithHandler(IRequest<TResponse> request, CancellationToken cancellationToken,
    ServiceFactory serviceFactory, RequestHandlerHandleDelegate<TRequest, TResponse> endHandler)
{
    Task<TResponse> Handler() => endHandler != null ? endHandler((TRequest)request) : GetHandler<IRequestHandler<TRequest, TResponse>>(serviceFactory).Handle((TRequest)request, cancellationToken);

    return serviceFactory
        .GetInstances<IPipelineBehavior<TRequest, TResponse>>()
        .Reverse()
        .Aggregate((RequestHandlerDelegate<TResponse>)Handler, (next, pipeline) => () => pipeline.Handle((TRequest)request, cancellationToken, next))();
}

I don't know whether you want this to be included in this library (as it kind of defeats the purpose of a Mediator), but I see a lot of cases where it's not really added because it's a Mediator but because of the Request/Command pipeline.

I'm ok to fix my POC and create a PR if it's seen as a good addition :).

Most helpful comment

This is purely my opinion and im (obviously) not related to the project in any way.
I dont think that this really belongs in the core project. One option would be to implement a custom mediator and expose your own interface if you really need the functionality. There are a couple of samples which you have probably already seen. Wouldn't this solve the problem?

Regarding the navigation issue (when not debugging): I think I saw the tip from Jimmy some time ago. I nowadays name my requests in such a way that it is easy to navigate to the handlers.
PingRequest => PingRequestHandler. PongCommand => PongCommandHandler. You get the idea. Highlight the request class, CTRL+T and bam your handler is right there in the Go To dropdown.

>All comments

This is purely my opinion and im (obviously) not related to the project in any way.
I dont think that this really belongs in the core project. One option would be to implement a custom mediator and expose your own interface if you really need the functionality. There are a couple of samples which you have probably already seen. Wouldn't this solve the problem?

Regarding the navigation issue (when not debugging): I think I saw the tip from Jimmy some time ago. I nowadays name my requests in such a way that it is easy to navigate to the handlers.
PingRequest => PingRequestHandler. PongCommand => PongCommandHandler. You get the idea. Highlight the request class, CTRL+T and bam your handler is right there in the Go To dropdown.

Was this page helpful?
0 / 5 - 0 ratings