MitMediator 7.0.0
MitMediator
Fast mediator for handling requests, commands, notifications, and streams with ValueTask and ordered pipelines
β¨ Features
- Supports
IRequest<TResponse>andIRequest(void-style) - Custom handlers via
IRequestHandler<,>andIRequestHandler<> - Supports both
ValueTask(for modern, efficient handlers) andTask(for compatibility with MediatR-style handlers) - Enables middleware-style pipelines using
IPipelineBehavior<TRequest, TResponse>. A pipeline behavior can be defined for all or specific request types. - Supports
INotificationHandlerwith serial and parallel publishing - Ordered execution of pipeline behaviors
- Simple registration through
AddMitMediator()or assembly scanning - Supports
IStreamRequestHandleandIStreamPipelineBehavior
π Getting Started
Installation
dotnet add package MitMediator -v 7.0.0
βοΈ Example Usage
This example shows a basic setup of MitMediator that demonstrates:
- Request handling via PingRequestHandler
- Notification publishing via NotificationHandler
- Two pipeline behaviors: HeightBehavior and LowBehavior
using Microsoft.Extensions.DependencyInjection;
using MitMediator;
var services = new ServiceCollection();
services
.AddMitMediator(typeof(PingRequestHandler).Assembly)
.AddTransient(typeof(IPipelineBehavior<,>), typeof(HeightBehavior<,>))
.AddTransient(typeof(IPipelineBehavior<,>), typeof(LowBehavior<,>));
var provider = services.BuildServiceProvider();
var mediator = provider.GetRequiredService<IMediator>();
// HeightBehavior: Handling PingRequest
// LowBehavior: Handling PingRequest
// PingRequestHandler: Pong
// NotificationHandler: Notification!
// LowBehavior: Handled PingRequest
// HeightBehavior: Handled PingRequest
string result = await mediator.SendAsync<PingRequest, string>(new PingRequest(), CancellationToken.None);
Console.WriteLine(result); //Pong result
public class PingRequest : IRequest<string> { }
public class PingRequestHandler : IRequestHandler<PingRequest, string>
{
private readonly IMediator _mediator;
public PingRequestHandler(IMediator mediator)
{
_mediator = mediator;
}
public ValueTask<string> HandleAsync(PingRequest request, CancellationToken cancellationToken)
{
Console.WriteLine("PingRequestHandler: Pong");
_mediator.PublishAsync(new Notification(), cancellationToken);
return ValueTask.FromResult("Pong result");
}
}
public class LowBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
public async ValueTask<TResponse> HandleAsync(TRequest request, IRequestHandlerNext<TRequest, TResponse> next, CancellationToken cancellationToken)
{
Console.WriteLine($"LowBehavior: Handling {typeof(TRequest).Name}");
var result = await next.InvokeAsync(request, cancellationToken);
Console.WriteLine($"LowBehavior: Handled {typeof(TRequest).Name}");
return result;
}
}
public class HeightBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
public async ValueTask<TResponse> HandleAsync(TRequest request, IRequestHandlerNext<TRequest, TResponse> next, CancellationToken cancellationToken)
{
Console.WriteLine($"HeightBehavior: Handling {typeof(TRequest).Name}");
var result = await next.InvokeAsync(request, cancellationToken);
Console.WriteLine($"HeightBehavior: Handled {typeof(TRequest).Name}");
return result;
}
}
public class Notification : INotification{}
public class NotificationHandler : INotificationHandler<Notification>
{
public ValueTask HandleAsync(Notification notification, CancellationToken cancellationToken)
{
Console.WriteLine($"NotificationHandler: Notification!");
return ValueTask.CompletedTask;
}
}
To use
Taskinstead ofValueTaskfor handlers, reference the MitMediator.Tasks namespace
π Migrating from MediatR
You can reuse your existing handlers with minimal modifications β just update the namespaces and registration calls
- Add the
MitMediatorpackagedotnet add package MitMediator -v 7.0.0 - In your request files, replace the namespace
MediatRwithMitMediator - In your request handler files, replace the namespace
MediatRwithMitMediator(andMitMediator.TasksforTaskresult) - Update your dependency injection setup: replace
.AddMediatR(...)with.AddMitMediator() - If you're implementing
INotificationHandler, useValueTaskinstead ofTask - If you're implementing
IPipelineBehavior, useValueTaskinstead ofTaskandIRequestHandlerNext<TRequest, TResponse>instead ofRequestHandlerDelegate<TResponse>. Usenext.InvokeAsync(request, cancellationToken)for next pipe - For handlers with void result, use
Task<Unit>instead ofTask(returnUnit.Value) - (Optional) Change all
mediator.Send(request, ct)tomediator.SendAsync<TRequset, TResponse>(request, ct)(ormediator.Send<TRequset, TResponse>(request, ct)forTaskresult) - Build and run your project β youβre all set!
Use
SendAsync<TRequset, TResponse>(request, ct)for best performance orSend(request, ct)for backward compatibility with MediatR-style semantics
MitMediator is designed to feel familiar for those coming from MediatR. Core concepts like IRequest, IRequestHandle, and pipeline behaviors are preserved β but with a cleaner interface and support for ValueTask out of the box.
π Comparison: MitMediator vs. MediatR
Performance
| Mediator | Method | Mean (ns) | Allocated (B) |
|---|---|---|---|
| MediatR | Send (return result) | 167.5 | 384 |
| MitMediator | SendAsync (return result) | 69.99 | 0 |
| MediatR | Send (return result, use behaviors) | 282.76 | 864 |
| MitMediator | SendAsync (return result, use behaviors) | 68.26 | 0 |
| MediatR | Send (Return void) | 158.71 | 312 |
| MitMediator | SendAsync (Return void) | 67.15 | 0 |
| MediatR | Publish | 200.52 | 592 |
| MitMediator | PublishAsync | 75.52 | 32 |
| MediatR | CreateStream (return stream, use behavior) | 1,260.9 | 1200 |
| MitMediator | CreateStream (return stream, use behavior) | 268.9 | 120 |
Features
| Feature | MitMediator | MediatR |
|---|---|---|
| Return types | ValueTask (default, allocation-friendly) |
Task (standard async support) |
| Send methods | Strongly typed requests (SendAsync<TRequest, TResponse>) |
Loosely typed requests (Send(request)) |
| DI Registration | AddMitMediator() with optional assembly scanning |
AddMediatR() with assemblies explicitly specified |
| Extensibility | Designed for lightweight extension and customization | More opinionated; extensibility requires deeper integration |
| Notification publishing | Serial and parallel | Only serial out of the box |
| Performance Focus | Async-first, zero-allocation for ValueTask |
Flexible but not optimized for ValueTask |
| License & Availability | MIT | Reciprocal Public License 1.5 (RPL1.5) and commercial license |
π§ͺ Testing
This project includes comprehensive unit tests with 100% code coverage. All tests are included in the repository
π§© Extensions
MitMediator.AutoApi - automatic creation of API endpoints for requests
π License
MIT
No packages depend on MitMediator.
.NET 7.0
- Microsoft.Extensions.DependencyInjection (>= 7.0.0)