Middlewares
A middleware is a piece of logic that is executed between the mediator and the message handler. It has been designed to be very similar to Asp.Net Core middlewares. You can use middlewares to create any pipeline that you need for your queries and events.
Each middleware can do the following things:
Choose to invoke the next element in the pipeline.
Do logic before and after calling the next element in the pipeline.
Note
The middlewares are invoked in the same registration order.
Query Middleware
A query middleware allows you to create a specific pipeline for a query.
Middleware creation
To create a query middleware you have to implement the IQueryMiddleware<TQuery,TResult>
generic interface.
/// <summary>
/// Interface to implement a middleware to process a query before it reaches it's handler.
/// <typeparam name="TQuery">Query type</typeparam>
/// <typeparam name="TResult">Query response type</typeparam>
/// </summary>
public interface IQueryMiddleware<in TQuery, TResult> where TQuery : IQuery<TResult>
{
/// <summary>
/// Invoke the middleware logic
/// </summary>
/// <param name="query">Query object</param>
/// <param name="cancellationToken"></param>
/// <param name="next">Delegate that encapsulates a call to the next element in the pipeline</param>
/// <returns></returns>
Task<TResult> Invoke(TQuery query, CancellationToken cancellationToken, NextMiddlewareDelegate<TResult> next);
}
For example:
public class SampleQueryLoggerMiddleware : IQueryMiddleware<MyQuery, string>
{
private readonly ILogger<SampleQueryLoggerMiddleware> _logger;
public SampleQueryLoggerMiddleware(ILogger<SampleQueryLoggerMiddleware> logger)
{
_logger = logger;
}
public async Task<string> Invoke(MyQuery query, CancellationToken cancellationToken, NextMiddlewareDelegate<string> next)
{
_logger.LogDebug("Query log: ", query);
//invoke the next middleware in the pipeline
return await next();
}
}
Note
The NextMiddlewareDelegate<TResult> next
parameter is a delegate
that encapsulates the call to the next element in the pipeline.
Query middleware pipeline
The following diagram demonstrates how middlewares are invoked under the hood.
Important
You have to invoke next
to execute the next element in the pipeline.
You can short circuit the pipeline simply don’t invoking next
.
Event Middleware
An event middleware allows you to create a specific pipeline for an event.
Middleware creation
To create an event middleware you have to implement the IEventMiddleware<TEvent>
generic interface.
/// <summary>
/// Interface to implement a middleware to process an event before it reaches it's handlers.
/// <typeparamref name="TEvent">Event type</typeparam>
/// </summary>
public interface IEventMiddleware<in TEvent> where TEvent : IEvent
{
/// <summary>
/// Invoke the middleware logic
/// </summary>
/// <param name="event">Event object</param>
/// <param name="cancellationToken"></param>
/// <param name="next">Delegate that encapsulates a call to the next element in the pipeline</param>
/// <returns></returns>
Task Invoke(TEvent @event, CancellationToken cancellationToken, NextMiddlewareDelegate next);
}
For example:
public class SampleEventLoggerMiddleware : IEventMiddleware<MyEvent>
{
private readonly ILogger<SampleEventLoggerMiddleware> _logger;
public SampleEventLoggerMiddleware(ILogger<SampleEventLoggerMiddleware> logger)
{
_logger = logger;
}
public async Task Invoke(MyEvent @event, CancellationToken cancellationToken, NextMiddlewareDelegate next)
{
_logger.LogDebug("Event log: ", @event);
//invoke the next middleware in the pipeline
await next();
}
}
Note
The NextMiddlewareDelegate next
parameter is a delegate
that encapsulates the call to the next element in the pipeline.
Event middleware pipeline
The following diagram demonstrates how middlewares are invoked under the hood.
Important
You have to invoke next
to execute the next element in the pipeline.
You can short circuit the pipeline simply don’t invoking next
.