DispatchR.Mediator
1.0.2
See the version list below for details.
dotnet add package DispatchR.Mediator --version 1.0.2
NuGet\Install-Package DispatchR.Mediator -Version 1.0.2
<PackageReference Include="DispatchR.Mediator" Version="1.0.2" />
<PackageVersion Include="DispatchR.Mediator" Version="1.0.2" />
<PackageReference Include="DispatchR.Mediator" />
paket add DispatchR.Mediator --version 1.0.2
#r "nuget: DispatchR.Mediator, 1.0.2"
#:package DispatchR.Mediator@1.0.2
#addin nuget:?package=DispatchR.Mediator&version=1.0.2
#tool nuget:?package=DispatchR.Mediator&version=1.0.2
DispatchR ๐
A High-Performance Mediator Implementation for .NET,
** Minimal memory footprint. Blazing-fast execution. **
โก Key Features
- ๐งฉ Built entirely on top of Dependency Injection
- ๐ซ Zero runtime reflection after registration
- ๐ง Choose your handler return type:
Task,ValueTask, orSynchronous Method - ๐ง Allocates nothing on the heap โ ideal for high-throughput scenarios
- โก Outperforms existing solutions in most real-world benchmarks
- ๐ Seamlessly compatible with MediatR โ migrate with minimal effort
๐ก Tip: If you're looking for a mediator with the raw performance of hand-written code, DispatchR is built for you.
Syntax Comparison: DispatchR vs MediatR
In the following, you will see the key differences and implementation details between MediatR and DispatchR.
โ Request Definition
MediatR
public sealed class PingMediatR : IRequest<int> { }
DispatchR
- Sending
TRequesttoIRequest - Precise selection of output for both
asyncandsynchandlers- Ability to choose between
TaskandValueTask
- Ability to choose between
public sealed class PingDispatchR : IRequest<PingDispatchR, ValueTask<int>> { }
โ Handler Definition
MediatR
public sealed class PingHandlerMediatR : IRequestHandler<PingMediatR, int>
{
public Task<int> Handle(PingMediatR request, CancellationToken cancellationToken)
{
return Task.FromResult(0);
}
}
DispatchR (Don't change)
public sealed class PingHandlerDispatchR : IRequestHandler<PingDispatchR, ValueTask<int>>
{
public ValueTask<int> Handle(PingDispatchR request, CancellationToken cancellationToken)
{
return ValueTask.FromResult(0);
}
}
โ Pipeline Behavior
MediatR
public sealed class LoggingBehaviorMediat : IPipelineBehavior<PingMediatR, int>
{
public Task<int> Handle(PingMediatR request, RequestHandlerDelegate<int> next, CancellationToken cancellationToken)
{
return next(cancellationToken);
}
}
DispatchR
- Use Chain of Responsibility pattern
public sealed class LoggingBehaviorDispatchR : IPipelineBehavior<PingDispatchR, ValueTask<int>>
{
public required IRequestHandler<PingDispatchR, ValueTask<int>> NextPipeline { get; set; }
public ValueTask<int> Handle(PingDispatchR request, CancellationToken cancellationToken)
{
return NextPipeline.Handle(request, cancellationToken);
}
}
๐ Summary
- DispatchR lets the request itself define the return type.
- No runtime reflection in DispatchR โ it's optimized for performance.
- No static behavior chains โ pipelines are chained via DI and handler wiring.
- Supports
void,Task, orValueTaskas return types.
Ideal for high-performance .NET applications.
โก How DispatchR Achieves High Performance
DispatchR is designed with one goal in mind: maximize performance with minimal memory usage. Here's how it accomplishes that:
๐ What Happens Inside the Send Method?
public TResponse Send<TRequest, TResponse>(IRequest<TRequest, TResponse> request,
CancellationToken cancellationToken) where TRequest : class, IRequest, new()
{
return serviceProvider
.GetRequiredService<IRequestHandler<TRequest, TResponse>>()
.Handle(Unsafe.As<TRequest>(request), cancellationToken);
}
โ Only the handler is resolved and directly invoked!
But the real magic happens behind the scenes when DI resolves the handler dependency:
๐ก Tips: We cache the handler using DI, so in scoped scenarios, the object is constructed only once and reused afterward.
services.AddScoped(handlerInterface, sp =>
{
var pipelines = sp
.GetServices(pipelinesType)
.Select(s => Unsafe.As<IRequestHandler>(s)!);
IRequestHandler lastPipeline = Unsafe.As<IRequestHandler>(sp.GetService(handler))!;
foreach (var pipeline in pipelines)
{
pipeline.SetNext(lastPipeline);
lastPipeline = pipeline;
}
return lastPipeline;
});
โจ This elegant design chains pipeline behaviors at resolution time โ no static lists, no reflection, no magic.
๐ง Smarter LINQ: Zero Allocation
To further reduce memory allocations, DispatchR uses zLinq, a zero-allocation LINQ implementation, instead of the default LINQ. This means even in heavy pipelines and high-frequency requests, memory remains under control.
Of course, our goal is to stay dependency-free โ but for now, I think it's totally fine to rely on this as a starting point!
๐ชด How to use?
It's simple! Just use the following code:
builder.Services.AddDispatchR(typeof(MyCommand).Assembly);
This code will automatically register all pipelines by default. If you need to register them in a specific order, you can either add them manually or write your own reflection logic:
builder.Services.AddDispatchR(typeof(MyCommand).Assembly, withPipelines: false);
builder.Services.AddScoped<IPipelineBehavior<MyCommand, int>, PipelineBehavior>();
builder.Services.AddScoped<IPipelineBehavior<MyCommand, int>, ValidationBehavior>();
๐ก Key Notes:
- Automatic pipeline registration is enabled by default
- Manual registration allows for custom pipeline ordering
- You can implement custom reflection if needed
โจ How to install?
dotnet add package DispatchR.Mediator --version 1.0.0
๐งช Bechmark Result:
This benchmark was conducted using MediatR version 12.5.0 and the stable release of Mediator Source Generator, version 2.1.7. Version 3 of Mediator Source Generator was excluded due to significantly lower performance.
1. MediatR vs Mediator Source Generator vs DispatchR With Pipeline
2. MediatR vs Mediator Source Generator vs DispatchR Without Pipeline
โจ Contribute & Help Grow This Package! โจ
We welcome contributions to make this package even better! โค๏ธ
- Found a bug? ๐ โ Open an issue
- Have an idea? ๐ก โ Suggest a feature
- Want to code? ๐ฉ๐ป โ Submit a PR
Let's build something amazing together! ๐
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
-
net9.0
- Microsoft.Extensions.DependencyInjection (>= 9.0.4)
- ZLinq (>= 1.4.2)
- ZLinq.DropInGenerator (>= 1.4.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on DispatchR.Mediator:
| Package | Downloads |
|---|---|
|
Vexor.Application
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.3.1 | 7,339 | 7/11/2026 |
| 2.3.0 | 33,780 | 5/29/2026 |
| 2.2.0 | 17,145 | 5/9/2026 |
| 2.1.2 | 166 | 5/8/2026 |
| 2.1.1 | 138,675 | 10/8/2025 |
| 2.1.0 | 377 | 10/6/2025 |
| 2.0.1 | 4,329 | 9/20/2025 |
| 2.0.0 | 5,076 | 8/24/2025 |
| 1.3.3 | 7,225 | 8/3/2025 |
| 1.3.2 | 877 | 7/9/2025 |
| 1.3.1 | 217 | 7/7/2025 |
| 1.3.0 | 227 | 6/26/2025 |
| 1.2.1 | 364 | 6/11/2025 |
| 1.2.0 | 184 | 5/31/2025 |
| 1.1.0 | 247 | 5/19/2025 |
| 1.0.2 | 258 | 5/4/2025 |
| 1.0.0 | 225 | 5/4/2025 |
| 0.0.4 | 273 | 5/2/2025 |