A super lightweight mediator pattern library with no frills. π»
A simple implementation for .NET that provides request/handler pattern capabilities without the overhead of a full-featured library.
NOTE: BareMediator is free for individuals and companies with less than USD 500,000 in ARR. Above that threshold, check licensing and pricing.
- Simple request/response pattern
- Automatic handler discovery and registration
- Dependency injection integration
- Async/await support
- Minimal dependencies
- No notifications/events
- No pipeline behaviors
- No streaming
Install the nuget package via the .NET CLI:
dotnet add package BareMediatorservices.AddMediator<Program>(); // Scans the assembly containing Program
// or
services.AddMediator(typeof(Program).Assembly, typeof(OtherType).Assembly);Note: BareMediator is instantiated as a transient service.
using BareMediator;
public record GetUserRequest
: IRequest<GetUserResponse>
{
public Guid UserId { get; init; }
}
public record GetUserResponse
{
public Guid UserId { get; init; }
public string Name { get; init; }
}using BareMediator;
public class GetUserRequestHandler
: IRequestHandler<GetUserRequest, GetUserResponse>
{
public async Task<GetUserResponse> Handle(GetUserRequest request, CancellationToken cancellationToken)
{
// Your logic here
return new GetUserResponse
{
UserId = request.UserId,
Name = "John Doe"
};
}
}public class UsersController(IMediator mediator)
: ControllerBase
{
private readonly IMediator _mediator = mediator;
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(Guid id)
{
GetUserRequest request = new { UserId = id };
GetUserResponse response = await _mediator.Send(request);
return Ok(response);
}
}For commands that don't return data (e.g., DeleteUserCommand, UpdateSettingsCommand), use the Unit type instead of void:
// Command
public record DeleteUserCommand(Guid UserId) : IRequest<Unit>;
// Handler
public class DeleteUserCommandHandler(IUserRepository repository)
: IRequestHandler<DeleteUserCommand, Unit>
{
private readonly IUserRepository _repository = repository;
public async Task<Unit> Handle(DeleteUserCommand request, CancellationToken cancellationToken)
{
await _repository.DeleteAsync(request.UserId, cancellationToken);
return Unit.Value; // Represents successful completion
}
}
// Usage
await _mediator.Send(new DeleteUserCommand(userId));Why Unit instead of void?
- C# doesn't support
voidas a generic type parameter Unitis a singleton value type that represents "no data"- All
Unitinstances are equal and have no meaningful state - Compatible with MediatR's
Unittype for easy migration
MediatR is a fantastic library, but if you only need request/handler capabilities, you're pulling in a much larger library with features you don't use.
BareMediator provides just the essentials:
- Lightweight: Nearly 7x smaller than MediatR
- Fast: No pipeline overhead
- Simple: Only 6 files, <200 lines of code: easy to understand and debug
- Compatible: Drop-in replacement for basic MediatR usage
Everywhere simply replace:
// Before
using MediatR;
// After
using BareMediator;In your Program.cs replace also:
// Before
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Program>());
// After
services.AddMediator<Program>();All your existing IRequest<T>, IRequestHandler<TRequest, TResponse>, and IMediator code will work as-is!