Launch OfferSubscribe now and get 3 months free.

Full access to all commercial features. No credit card required.

40Days
:
06Hrs
:
45Min
:
01Sec
HIGH-PERFORMANCENATIVE AOTSOURCE GENERATORS

Zero structural overhead mediator
Compiled at build time.
Runs like a direct call.

No reflection. No runtime overhead.

01 · Architecture

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.

7.2ns
per Send
72B
constant alloc
0
reflection
01 / 04Compile-time pipeline

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
Program.cs · quick start
1Define query + handler
public record Ping() : IQuery<int>;
 
public class PingHandler : IQueryHandler<Ping, int>
{
  public ValueTask<int> Handle(Ping request, CancellationToken ct)
    => new ValueTask<int>(42);
}
2Register · one call
services.AddMediator(_ => { });
// registers handlers, precompiles pipelines, freezes dispatch
3Send
var result = await mediator.Send(new Ping());
Setup
3 lines
Composition
At compile time
AOT
Safe
Realistic pipeline · ns/op↓ lower is better
Direct call
674 ns
DSoftStudio
667 ns
DispatchR
667 ns
Mediator (SG)
718 ns
MediatR 14
857 ns
0.99×
vs direct call
255 B
total alloc
3.8×
less than MediatR
02 / 04Memory profile

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
03 / 04Determinism

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
NotificationDispatch.g.cs · source-generated
// closed switch table — exact-type routing, no inheritance walk
switch (notification)
{
case UserRegistered u: return Publish<UserRegistered>(u, ct);
case OrderPlaced p: return Publish<OrderPlaced>(p, ct);
case BaseEvent: // never emitted — MediatR would fan out here
}
✓ Deterministic · 0 B allocated · 4.5 ns
PingHandler.cs · diff
-using MediatR;
- public Task<int> Handle(Ping req, CancellationToken ct)
+using DSoftStudio.Mediator.Abstractions;
+using DSoftStudio.Mediator;
+ public ValueTask<int> Handle(Ping req, CancellationToken ct)
Lifetime
→ Singleton
Behavior next
IRequestHandler
Effort
Low
04 / 04Migration

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
02 · Real-world benchmark

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.

0.99×overhead
vs direct call · 3-behavior pipeline
667 ns through the mediator. 674 ns calling the handler directly.
Library
Direct call
Mediator pipeline
Overhead
DSoftStudio.Mediator
674 ns
271 B
667 ns
255 B
0.99×
≈ direct
DispatchR 2.1
661 ns
271 B
667 ns
255 B
1.01×
Mediator (SG) 3.0
679 ns
270 B
718 ns
397 B
1.06×
1.5× alloc
MediatR 14.1
714 ns
270 B
857 ns
1,032 B
1.20×
3.8× alloc
* BenchmarkDotNet · .NET 10 · isolated processes · pipeline: Validation → Logging → Metrics → async DB write.
Pipeline depth scalingSend · isolated microbench
↓ lower is better
DSoftStudio
no behaviors7.2 ns
3 behaviors13.8 ns
5 behaviors15.6 ns
0 → 5 scale: 2.2×
Mediator (SG)
no behaviors12.2 ns
3 behaviors28.0 ns
5 behaviors36.8 ns
0 → 5 scale: 3.0×
DispatchR
no behaviors33.4 ns
3 behaviors53.2 ns
5 behaviors54.1 ns
0 → 5 scale: 1.6×
MediatR
no behaviors41.3 ns
3 behaviors108 ns
5 behaviors153 ns
0 → 5 scale: 3.7×
With 5 behaviors stacked, DSoftStudio is 9.8× faster than MediatR (15.6 ns vs 153 ns) — and still allocates the same 72 B.
01

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.

02

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.

03

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.

04

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.

Mental model

This mediator does not execute your pipeline.

It becomes your pipeline at compile time.

2000+
Parallel requests tested
6+
Behaviors deep · chaos-tested
100%
Native AOT + trimming
0
Reflection on hot path
03 · Ship

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.

7.2ns
per Send
4.5ns
per Publish · 0 B
72B
constant · any depth
100%
Native AOT + trimming
~/your-app · zsh
.NET 10
$ dotnet add package DSoftStudio.Mediator
Determining projects to restore...
info : package 'DSoftStudio.Mediator' version '1.3.0' added to 'YourApp.csproj'.
log : Restored YourApp.csproj (in 824 ms).
// Program.cs
services.AddMediator(builder => {
builder.AddOpenBehavior(typeof(LoggingBehavior<,>));
});
$ dotnet run
DSoftStudio.Mediator: generated 4 dispatchers · 0 ms
Listening on http://localhost:5000
dotnet add package DSoftStudio.Mediator