AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻譯準備中
A zero-allocation mediator library for .NET 10. Roslyn source generator wires all dispatch at compile time — no reflection, no dictionaries, no virtual dispatch.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
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.
The generator package must also be added as an analyzer:檢視完整 README ↗A source-generated MediatR alternative for .NET 8 and .NET 10: requests, notifications and streams dispatched without reflection, with no allocations on the Send and Publish hot path, ready for NativeAOT.
Send and Publish. The static Mediator path, pipeline behaviors included, is held at zero bytes by AllocationGate tests. MediatR allocates 224 B per Send and 792 B per single-handler Publish in the same benchmark.Send and Publish in the same BenchmarkDotNet run. Through IMediator resolved from a new scope per call, the way an ASP.NET Core request does, it is still 1.4–3.2x faster and allocates 176–200 B against MediatR's 352–1,232 B.dotnet add package ZeroAlloc.Mediator
dotnet add package ZeroAlloc.Mediator.Generator
The second package is the source generator; it is added as a private development dependency. See Getting Started for multi-project solutions.
using ZeroAlloc.Mediator;
decimal total = await Mediator.Send(new AddToCart(Quantity: 3, UnitPrice: 9.99m));
Console.WriteLine(total); // 29.97
public readonly record struct AddToCart(int Quantity, decimal UnitPrice) : IRequest<decimal>;
public sealed class AddToCartHandler : IRequestHandler<AddToCart, decimal>
{
public ValueTask<decimal> Handle(AddToCart request, CancellationToken ct)
=> ValueTask.FromResult(request.Quantity * request.UnitPrice);
}
Mediator.Send(AddToCart) is an overload the generator wrote for this request, so the call is checked by the compiler and dispatches straight to the handler. In an ASP.NET Core app, call builder.Services.AddMediator() and inject IMediator; see Dependency Injection.
Unit for none.[ParallelNotification], and handlers for a base interface receive derived notifications too.IAsyncEnumerable<T> results through CreateStream.AddMediator() and IMediator, with handler lifetimes you choose.Optional packages plug into the pipeline; reference one and call its With...() method on AddMediator():
ZeroAlloc.Mediator.Validation: runs the ZeroAlloc.Validation validator for a request before its handler. WithValidation()ZeroAlloc.Mediator.Authorization: gates dispatch on [RequirePolicy] checks from ZeroAlloc.Authorization. WithAuthorization()ZeroAlloc.Mediator.Cache: caches responses for requests marked [CacheResponse]. WithCache()ZeroAlloc.Mediator.Resilience: retry, timeout and circuit-breaker policies through ZeroAlloc.Resilience. WithResilience()ZeroAlloc.Mediator.Telemetry: OpenTelemetry request count and duration metrics. WithTelemetry().NET 10, BenchmarkDotNet, ZeroAlloc.Mediator and MediatR in the same run. Allocations are exact; speed is a same-run ratio.
| Operation | Speed vs MediatR | ZeroAlloc.Mediator | MediatR |
|---|---|---|---|
Send, static Mediator | 3.9x faster | 0 B | 224 B |
Publish, 1 handler, static Mediator | 16x faster | 0 B | 792 B |
Send via IMediator, new DI scope per call | 1.5x faster | 176 B | 496 B |
The 176 B is the DI scope and the transient IMediator, not the dispatch. The static rows hold with no factory registered, for a handler without instance state. The performance page has every row, including pipelines and streaming, and explains where each byte comes from.
ZeroAlloc.Mediator.Validation runs before each handler.ZeroAlloc.Mediator.Authorization checks before dispatch.Result response and the validation and authorization packages return failures in it instead of throwing.