High-performance Mediator pattern implementation for .NET with CQRS support. Inspired by MediatR with focus on performance and simplicity.
- 🚀 High Performance - Static caching, minimal allocations, aggressive inlining
- 📦 CQRS Ready - Request/Response, Commands, Queries, and Notifications
- 🔌 Pipeline Behaviors - Cross-cutting concerns (logging, validation, caching)
- ⚡ Streaming Support -
IAsyncEnumerablefor large datasets - 🛡️ Validation - Built-in validation behavior with custom validators
- 🎯 Pre/Post Processors - Execute logic before/after handlers
- 💉 DI Integration - Native Microsoft.Extensions.DependencyInjection support
dotnet add package Mediator
dotnet add package Mediator.Extensions.DependencyInjection// Request
public record GetUserQuery(int UserId) : IRequest<UserDto>;
// Handler
public class GetUserHandler : IRequestHandler<GetUserQuery, UserDto>
{
public async Task<UserDto> Handle(GetUserQuery request, CancellationToken ct)
{
return new UserDto(request.UserId, "John Doe");
}
}services.AddMediator(config =>
{
config.AddAssembly(typeof(Program).Assembly);
});public class UserController
{
private readonly IMediator _mediator;
public UserController(IMediator mediator) => _mediator = mediator;
public async Task<UserDto> GetUser(int id)
{
return await _mediator.Send(new GetUserQuery(id));
}
}public record CreateUserCommand(string Name, string Email) : IRequest;
public class CreateUserHandler : IRequestHandler<CreateUserCommand, Unit>
{
public async Task<Unit> Handle(CreateUserCommand request, CancellationToken ct)
{
// Create user logic
return Unit.Value;
}
}public record UserCreated(int UserId, string Name) : INotification;
public class SendWelcomeEmail : INotificationHandler<UserCreated>
{
public async Task Handle(UserCreated notification, CancellationToken ct)
{
// Send email
}
}
public class LogUserCreated : INotificationHandler<UserCreated>
{
public async Task Handle(UserCreated notification, CancellationToken ct)
{
// Log event
}
}
// Usage
await _mediator.Publish(new UserCreated(1, "John"));public record GetLogsStream(DateTime From) : IStreamRequest<LogEntry>;
public class GetLogsHandler : IStreamRequestHandler<GetLogsStream, LogEntry>
{
public async IAsyncEnumerable<LogEntry> Handle(
GetLogsStream request,
[EnumeratorCancellation] CancellationToken ct)
{
await foreach (var log in _db.GetLogsAsync(request.From, ct))
{
yield return log;
}
}
}public class LoggingBehavior<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
_logger.LogInformation("Handling {Request}", typeof(TRequest).Name);
var response = await next();
_logger.LogInformation("Handled {Request}", typeof(TRequest).Name);
return response;
}
}
// Registration
services.AddMediator(config =>
{
config.AddAssembly(typeof(Program).Assembly);
config.AddBehavior(typeof(LoggingBehavior<,>));
});public class CreateUserValidator : IValidator<CreateUserCommand>
{
public Task<ValidationResult> ValidateAsync(
CreateUserCommand request,
CancellationToken ct)
{
if (string.IsNullOrEmpty(request.Name))
return Task.FromResult(
ValidationResult.Failure("Name", "Name is required"));
return Task.FromResult(ValidationResult.Success);
}
}
// Registration
services.AddMediator(config =>
{
config.AddAssembly(typeof(Program).Assembly);
config.AddBehavior(typeof(ValidationBehavior<,>));
});
services.AddTransient<IValidator<CreateUserCommand>, CreateUserValidator>();services.AddMediator(config =>
{
// Scan assemblies for handlers
config.AddAssembly(typeof(Program).Assembly);
// Configure lifetimes
config.MediatorLifetime = ServiceLifetime.Scoped;
config.HandlerLifetime = ServiceLifetime.Transient;
config.BehaviorLifetime = ServiceLifetime.Transient;
// Add behaviors (executed in order)
config.AddBehavior(typeof(LoggingBehavior<,>));
config.AddBehavior(typeof(ValidationBehavior<,>));
config.AddBehavior(typeof(RequestPreProcessorBehavior<,>));
config.AddBehavior(typeof(RequestPostProcessorBehavior<,>));
});The library includes 79 comprehensive unit tests covering:
- ✅ Request/Response handling
- ✅ Notifications (multiple handlers)
- ✅ Pipeline behaviors
- ✅ Pre/Post processors
- ✅ Validation
- ✅ Streaming with IAsyncEnumerable
- ✅ Cancellation support
- ✅ Exception handling
cd tests/Mediator.Tests
dotnet testMediator/
├── src/
│ ├── Mediator/
│ │ ├── Abstractions/ # Interfaces
│ │ ├── Behaviors/ # Pipeline behaviors
│ │ ├── Exceptions/ # Custom exceptions
│ │ ├── Validation/ # Validation support
│ │ ├── Wrappers/ # Handler wrappers
│ │ ├── Mediator.cs # Main implementation
│ │ └── Unit.cs # Unit type for void returns
│ └── Mediator.Extensions.DependencyInjection/
│ ├── MediatorServiceConfiguration.cs
│ └── ServiceCollectionExtensions.cs
└── tests/
└── Mediator.Tests/ # Unit tests
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.