RmToolkit.Mediator
3.0.0
dotnet add package RmToolkit.Mediator --version 3.0.0
NuGet\Install-Package RmToolkit.Mediator -Version 3.0.0
<PackageReference Include="RmToolkit.Mediator" Version="3.0.0" />
<PackageVersion Include="RmToolkit.Mediator" Version="3.0.0" />
<PackageReference Include="RmToolkit.Mediator" />
paket add RmToolkit.Mediator --version 3.0.0
#r "nuget: RmToolkit.Mediator, 3.0.0"
#:package RmToolkit.Mediator@3.0.0
#addin nuget:?package=RmToolkit.Mediator&version=3.0.0
#tool nuget:?package=RmToolkit.Mediator&version=3.0.0
Mediator — lightweight, fast, assembly-scoped mediator for ASP.NET Core
A strongly-typed mediator implementation for .NET — similar to MediatR but explicitly designed for high performance, assembly-scoped behaviors, module isolation, and a clean extensibility model.
Supports:
- Requests (Commands / Queries)
- Notifications
- Pipeline behaviors (validation, idempotence, logging, transactions…)
- Assembly-filtered behaviors
- DI integration without reflection-heavy scanning
- Simple
ISender/IPublisherAPI
Table of contents
- Install
- Quick Start
- API Overview
- Configuration
- Using Requests (Commands / Queries)
- Using Notifications
- Pipeline Behaviors
- Advanced: Behavior Assembly Filtering
- Endpoint Example
- FAQ
- License
Install
dotnet add package RmToolkit.Mediator
or:
<PackageReference Include="RmToolkit.Mediator" Version="*" />
Quick Start
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMediator(conf =>
{
conf.HandlerAssembliesToRegister = new[]
{
typeof(Program).Assembly,
MyModule.AssemblyInfo.Assembly
};
conf.RequestHandlerLifetime = ServiceLifetime.Transient;
conf.NotificationPublisherLifetime = ServiceLifetime.Transient;
conf.AddBehavior(typeof(ValidationBehavior<,>));
});
var app = builder.Build();
app.Run();
API Overview
ISender
public interface ISender
{
Task<TResponse> SendAsync<TRequest, TResponse>(TRequest request, CancellationToken cancellationToken = default)
where TRequest : IRequest<TResponse>;
Task<TResponse> SendAsync<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default);
Task<Result> SendAsync(ICommand command, CancellationToken cancellationToken = default);
Task<Result<TResponse>> SendAsync<TResponse>(ICommand<TResponse> command, CancellationToken cancellationToken = default);
}
IPublisher
public interface IPublisher
{
Task PublishAsync<TNotification>(TNotification notification, CancellationToken cancellationToken = default)
where TNotification : INotification;
}
Marker Interfaces
public interface IRequest<TResponse> { }
public interface ICommand : IRequest<Result> { }
public interface ICommand<TResponse> : IRequest<Result<TResponse>> { }
public interface IQuery<TResponse> : IRequest<Result<TResponse>> { }
public interface INotification { }
Configuration
Your mediator is configured via:
builder.Services.AddMediator(conf =>
{
conf.HandlerAssembliesToRegister = [...];
conf.RequestHandlerLifetime = ServiceLifetime.Transient;
conf.NotificationPublisherLifetime = ServiceLifetime.Transient;
conf.AddBehavior(typeof(LoggingBehavior<,>));
});
✔ Updated AddBehavior API
public IMediatorConfigurator AddBehavior<TBehavior>(
Action<BehaviorBuilder>? configure = null,
ServiceLifetime lifetime = ServiceLifetime.Transient
)
=> AddBehavior(typeof(TBehavior), configure, lifetime);
public IMediatorConfigurator AddBehavior(
Type behaviorType,
Action<BehaviorBuilder>? configure = null,
ServiceLifetime lifetime = ServiceLifetime.Transient
)
{
_services.AddBehavior(behaviorType, configure, lifetime);
return this;
}
Using Requests (Commands / Queries)
Define a Command
public sealed record CreateOrder(int OrderId) : ICommand<int>;
Define a Handler
internal sealed class CreateOrderHandler : ICommandHandler<CreateOrder, int>
{
public async Task<Result<int>> Handle(CreateOrder request, CancellationToken ct)
{
return Result.Success(request.OrderId);
}
}
Send a Command
var result = await sender.SendAsync(new CreateOrder(55));
Using Notifications
Notification type
public sealed record UserRegistered(string UserId, string Email) : INotification;
Handler
internal class SendWelcomeEmailHandler : INotificationHandler<UserRegistered>
{
public Task Handle(UserRegistered notification, CancellationToken ct)
{
Console.WriteLine($"Sending welcome email to {notification.Email}");
return Task.CompletedTask;
}
}
Publishing
await publisher.PublishAsync(new UserRegistered("u1", "a@example.com"));
Pipeline Behaviors
A pipeline behavior wraps the request handler:
public interface IPipelineBehavior<TRequest, TResponse>
{
Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TRequest, TResponse> next,
CancellationToken ct
);
}
Example: Validation Behavior
public sealed class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TRequest, TResponse> next, CancellationToken ct)
{
Console.WriteLine("Validation...");
return await next(request, ct);
}
}
Register
conf.AddBehavior(typeof(ValidationBehavior<,>));
Advanced: Behavior Assembly Filtering
You can apply a behavior only to handlers in specific assemblies.
conf.AddBehavior(typeof(ModuleAIdempotentBehavior<,>),
b => b.ForAssemblyHandlers(ModuleA.AssemblyInfo.Assembly));
conf.AddBehavior(typeof(ModuleBIdempotentBehavior<,>),
b => b.ForAssemblyHandlers(ModuleB.AssemblyInfo.Assembly));
This lets you:
- isolate module behaviors
- enforce module-level cross-cutting rules
- avoid global behavior pollution
Endpoint Example
app.MapGet("/orders/{id:int}", async (int id, ISender sender) =>
{
var result = await sender.SendAsync(new CreateOrder(id));
return result;
});
FAQ
Do behaviors apply globally?
Yes, unless you configure assembly filtering using BehaviorBuilder.
Can I completely isolate module behaviors?
Yes — module-level behaviors execute only for handlers in the module’s assembly.
Are handlers auto-registered?
Yes, from assemblies listed in:
conf.HandlerAssembliesToRegister
License
MIT License — free for personal and commercial use.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Options (>= 10.0.0)
- RmToolkit.Mediator.Abstractions (>= 3.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0 | 340 | 12/7/2025 |
| 2.0.1 | 183 | 11/23/2025 |
| 2.0.0 | 250 | 11/16/2025 |
| 2.0.0-preview2 | 247 | 11/16/2025 |
| 2.0.0-preview1 | 176 | 11/15/2025 |
| 1.2.0 | 165 | 10/25/2025 |
| 1.1.0 | 197 | 10/9/2025 |