Zero structural overhead mediator
Compiled at build time.
Runs like a direct call.
No reflection. No runtime overhead.
A mediator that disappears
in your pipeline.
Four design decisions that keep DSoftStudio.Mediator within nanoseconds of a direct method call — even with five pipeline behaviors stacked on top.
No runtime composition.
Define a request, write a handler, register with one call. The source generator inspects your registrations and bakes the dispatch table at compile time — no reflection scan at startup, no expression trees, no delegate wrapping on the hot path.
- Three steps from zero to handler
- Real stack traces — no proxies, no DispatchProxy
- AOT-safe by construction
Constant allocation cost.
72 bytes per Send regardless of pipeline depth — 0, 3 or 5 behaviors, same allocation. Publish is zero-alloc. Constant allocation profiles give you tighter p99 / p999 latency under load.
- 72 B / Send · 0 B / Publish
- Pooled execution context
- Validated with BenchmarkDotNet · .NET 10
Notifications by exact compile-time type.
The source generator emits a closed dispatch table. Publishing DerivedEvent never invokes INotificationHandler<BaseEvent>. No reflection walk. No duplicate-handler problem.
- Closed dispatch table at compile time
- No accidental base-type fan-out
- Production-validated · 2000+ parallel requests
Straightforward migration.
IRequest, INotification and IStreamRequest markers are identical. Handlers swap Task for ValueTask, namespaces change, and registration moves to AddMediator. Pipeline behaviors need a small refactor — next() becomes next.Handle(request, ct). Your architecture stays.
- Same Send / Publish call sites
- Task → ValueTask in handlers · namespace swap
- Automatic Singleton/Transient handler lifetimes
- Step-by-step migration guide on docs.dsoftstudio.com
The cost of your pipeline should be
your code — not your mediator.
Microbenchmarks measure framework overhead in isolation. We measured something more honest: a real enterprise pipeline — Validation → Logging → Metrics → async DB write — across four mediator libraries.
GC pressure compounds at scale.
DSoft allocates 255 B per request in this pipeline — the same as calling the handler directly. Reflection-based mediators routinely allocate 4× as much; at 10k req/s that's ~8 MB/s of short-lived Gen0 garbage you weren't budgeting for.
Allocation profile shapes tail latency.
More GC collections mean more variance in p99 / p999. Constant-allocation pipelines produce tighter distributions — and tighter distributions are what SLAs are written against.
Pipeline depth shouldn't change cost.
DSoft allocates 72 B per Send whether you have 0, 3 or 5 behaviors. Reflection-based pipelines wrap each behavior in a new delegate and closure, so allocation grows linearly with depth — turning a 3-behavior chain into a much hotter Gen0 path than the 0-behavior baseline.
Implicit pipelines become opaque.
DSoft emits the full behavior chain at compile time — visible in the source-generated code, inspectable in your IDE, fully deterministic. Mediators that assemble the chain at runtime through service resolution hide the order: behavior interactions become inferred rather than read.
This mediator does not execute your pipeline.
It becomes your pipeline at compile time.
No surprises.
No hidden cost.
No runtime magic.
A source-generated mediator for .NET 8 / 9 / 10. Drop it into your composition root and keep your existing handlers.
dotnet add package DSoftStudio.Mediator