ZeroAlloc.Mediator.Validation
6.6.1
See the version list below for details.
dotnet add package ZeroAlloc.Mediator.Validation --version 6.6.1
NuGet\Install-Package ZeroAlloc.Mediator.Validation -Version 6.6.1
<PackageReference Include="ZeroAlloc.Mediator.Validation" Version="6.6.1" />
<PackageVersion Include="ZeroAlloc.Mediator.Validation" Version="6.6.1" />
<PackageReference Include="ZeroAlloc.Mediator.Validation" />
paket add ZeroAlloc.Mediator.Validation --version 6.6.1
#r "nuget: ZeroAlloc.Mediator.Validation, 6.6.1"
#:package ZeroAlloc.Mediator.Validation@6.6.1
#addin nuget:?package=ZeroAlloc.Mediator.Validation&version=6.6.1
#tool nuget:?package=ZeroAlloc.Mediator.Validation&version=6.6.1
ZeroAlloc.Mediator
ZeroAlloc.Mediator is a source-generated, zero-allocation mediator for .NET 8 and .NET 10. It supports request/response, notifications, and streaming without reflection or dynamic dispatch. The source generator eliminates the runtime overhead that reflection-based mediators incur by wiring all dispatch at compile time — no dictionaries, no virtual dispatch, no delegate allocation per request.
Install
dotnet add package ZeroAlloc.Mediator
The generator package must also be added as an analyzer:
<PackageReference Include="ZeroAlloc.Mediator.Generator" Version="*" OutputItemType="Analyzer" ReferenceOutputAssembly="false" PrivateAssets="all" />
Optional bridge packages add pipeline behaviors for other ZeroAlloc libraries:
| Package | Adds |
|---|---|
ZeroAlloc.Mediator.Cache |
[Cache]-driven response caching through ZeroAlloc.Cache — WithCache() |
ZeroAlloc.Mediator.Validation |
Request validation through ZeroAlloc.Validation ValidatorFor<T> — WithValidation() |
ZeroAlloc.Mediator.Resilience |
Retry, timeout and circuit-breaker policies through ZeroAlloc.Resilience — WithResilience() |
ZeroAlloc.Mediator.Telemetry |
OpenTelemetry metrics for Send — WithTelemetry() |
ZeroAlloc.Mediator.Authorization |
[Authorize]-gated dispatch through ZeroAlloc.Authorization policies — WithAuthorization() |
dotnet add package ZeroAlloc.Mediator.Cache # or .Validation, .Resilience, .Telemetry, .Authorization
PrivateAssets="all" matters in multi-project solutions: without it the analyzer flows transitively across a ProjectReference, so a downstream project runs the generator a second time and gets CS0436 on the duplicate generated types — a hard failure under TreatWarningsAsErrors.
Request types should be readonly record struct. A reference-type record still works, but the generator reports ZAM003 (a warning, which TreatWarningsAsErrors turns into a build failure) because dispatch then allocates.
Example
using ZeroAlloc.Mediator;
var builder = WebApplication.CreateBuilder(args);
// 3. Register IMediator with DI (the generator emits services.AddMediator() automatically)
builder.Services.AddMediator();
var app = builder.Build();
// 4. Send the request and use the result — fully strongly-typed, no boxing
app.MapPost("/orders", async (CreateOrder cmd, IMediator mediator, CancellationToken ct) =>
{
var id = await mediator.Send(cmd, ct); // returns OrderId
return Results.Created($"/orders/{id.Value}", id);
});
app.Run();
// 1. Define a request record and its expected response type
public readonly record struct OrderId(Guid Value);
public readonly record struct CreateOrder(string Product, int Qty) : IRequest<OrderId>;
// 2. Implement a handler — no constructor dependencies needed for this example
public class CreateOrderHandler : IRequestHandler<CreateOrder, OrderId>
{
public ValueTask<OrderId> Handle(CreateOrder request, CancellationToken ct)
=> ValueTask.FromResult(new OrderId(Guid.NewGuid()));
}
IMediatoris generated into your assembly and isinternal, so it cannot appear in apublicsignature. Endpoint lambdas andinternalservices are unaffected; see Visibility for the reasoning and the pattern for MVC controllers.
Performance
The static Mediator class is 36–160x faster than MediatR on Send and Publish, with zero heap allocation on those paths (.NET 10, i9-12900HK, BenchmarkDotNet). Through IMediator resolved from a new scope per call, the way an ASP.NET Core request does, it is 1.2–1.5x faster and allocates 176 B for the scope and the transient MediatorService.
| Operation | ZeroAlloc.Mediator | MediatR | Speedup | Alloc |
|---|---|---|---|---|
| Send | 0.5 ns | 78.3 ns | ~160x | 0 B vs 224 B |
| Send + pipeline | 2.8 ns | 101.8 ns | ~36x | 0 B vs 152 B |
| Publish (1 handler) | 6.1 ns | 243.8 ns | ~40x | 0 B vs 792 B |
| Publish (multi handler) | 6.6 ns | 332.4 ns | ~50x | 0 B vs 1,032 B |
| Send (via IMediator DI, scope per call) | 160.1 ns | 187.2 ns | ~1.2x | 176 B vs 496 B |
| Send + pipeline (via IMediator DI, scope per call) | 126.9 ns | 191.2 ns | ~1.5x | 176 B vs 352 B |
| Stream (5 items) | 202.8 ns | 654.4 ns | ~3x | 104 B vs 528 B |
The 0 B rows are pinned by AllocationGate tests, including with no factory registered. Without a factory, the static Mediator reuses one cached instance of a stateless handler: one with a parameterless constructor and no instance fields, auto-properties or captured primary-constructor parameters, on the class or any base class. That needs no configuration and no JIT help, so it holds on .NET 8 too. A handler that holds instance state is still created on every call, so its state never leaks between calls; that costs one handler object per call. Mediator.Configure(c => c.SetFactory(() => handler)) is only needed for such stateful handlers, to make them 0 B as well (#328).
The 104 B on the Stream row is the C# compiler's async IAsyncEnumerable<T> state machine for your handler method — every mediator dispatching to such handlers pays this; ZA.Mediator's own stream-dispatch contribution is 0 B. See docs/performance.md for the full benchmark table and zero-allocation design explanation.
Features
- Request/Response — strongly-typed
Sendoverloads per request type - Notifications — sequential or parallel (
[ParallelNotification]) dispatch - Streaming —
IAsyncEnumerable<T>viaCreateStream - Pipeline Behaviors — compile-time inlined middleware chain (logging, validation, etc.)
- Bridge Packages —
WithCache(),WithValidation(),WithResilience(),WithTelemetry()(OpenTelemetry metrics onIRequest<T>.Send; every dispatch opens a span with or without it),WithAuthorization()([Authorize]-gated dispatch viaZeroAlloc.Authorizationpolicies) - Polymorphic Notifications — base interface handlers are automatically included in concrete notification dispatch
- Analyzer Diagnostics — missing handlers, duplicates, and misconfigurations are build errors/warnings
- Zero Allocation —
ValueTask,readonly record struct, static dispatch, no closures;SendandPublishgated at 0 B byAllocationGatetests - Native AOT Compatible — no reflection at runtime; all dispatch is resolved at compile time by the source generator
Documentation
| Page | Description |
|---|---|
| Getting Started | Install and send your first request in five minutes |
| Requests & Handlers | Commands, queries, Unit responses, dispatch |
| Notifications | Events: sequential, parallel, polymorphic handlers |
| Streaming | IAsyncEnumerable<T> for large result sets |
| Pipeline Behaviors | Compile-time middleware: logging, validation, caching |
| Authorization | [Authorize]-gated dispatch via ZeroAlloc.Authorization policies |
| Dependency Injection | DI containers, IMediator, factory delegates |
| Diagnostics | ZAM001–ZAM011 compiler error reference with fixes |
| Performance | Zero-alloc internals, benchmark results, Native AOT |
| Advanced Patterns | Error handling, cancellation, scoped behaviors |
| Testing | Unit-test handlers, behaviors, and notifications |
| Migrating to 6.0 | Removed v1 registration shims, Validation 2, retired diagnostics |
License
MIT. See LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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 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 (>= 10.0.12)
- ZeroAlloc.Mediator (>= 6.6.1)
- ZeroAlloc.Results (>= 1.4.1)
- ZeroAlloc.Validation (>= 2.3.1)
-
net8.0
- Microsoft.Extensions.DependencyInjection (>= 10.0.12)
- ZeroAlloc.Mediator (>= 6.6.1)
- ZeroAlloc.Results (>= 1.4.1)
- ZeroAlloc.Validation (>= 2.3.1)
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 |
|---|---|---|
| 6.6.2 | 0 | 10/16/2026 |
| 6.6.1 | 79 | 10/15/2026 |
| 6.6.0 | 410 | 10/12/2026 |
| 6.5.0 | 287 | 10/11/2026 |
| 6.4.3 | 104 | 10/11/2026 |
| 6.4.2 | 502 | 10/11/2026 |
| 6.4.1 | 85 | 10/11/2026 |
| 6.4.0 | 100 | 10/10/2026 |
| 6.3.0 | 116 | 10/10/2026 |
| 6.2.0 | 86 | 10/9/2026 |
| 6.1.1 | 468 | 10/2/2026 |
| 6.1.0 | 177 | 9/30/2026 |
| 6.0.3 | 119 | 9/30/2026 |
| 6.0.2 | 178 | 9/28/2026 |
| 6.0.1 | 102 | 9/28/2026 |
| 6.0.0 | 980 | 9/27/2026 |
| 5.1.5 | 902 | 9/21/2026 |
| 5.1.4 | 254 | 9/20/2026 |
| 5.1.3 | 101 | 9/20/2026 |
| 5.1.2 | 110 | 9/20/2026 |