DSoftStudio Mediator

← Back to Documentation

Dispatch Pipeline

Runtime Execution Path

The hot path for Send() resolves a transient PipelineChainHandler from DI:

Mediator.Send<TRequest, TResponse>()
   │
   ▼
serviceProvider.GetRequiredService<PipelineChainHandler<TRequest, TResponse>>()
   │
   ▼
[no behaviors] → handler.Handle()                 ← fast path: direct call
[N behaviors]  → PipelineChainHandler (index++)   ← zero-alloc: interface dispatch, no closures

The runtime-typed Send(object) path uses a separate dispatch table:

SenderObjectExtensions.Send(ISender, object)
   │
   ▼
RequestObjectDispatch.Dispatch(Type, object, IServiceProvider, CancellationToken)
   │
   ▼
FrozenDictionary<Type, DispatchDelegate> lookup
   │
   ▼
Delegate casts object → TRequest, enters the same pipeline as Send<TRequest, TResponse>()

Service resolution goes directly through IServiceProvider — the standard DI container call that every mediator must make. This avoids additional container abstractions or service locators.

Note: Backward-compatible overloads (Send<TResponse>(IRequest<TResponse>), Publish(object), and CreateStream) use a one-time reflection + ConcurrentDictionary cache on first call per type. Subsequent calls hit the cache with zero reflection. The Send(object) overload uses a precompiled FrozenDictionary<Type, DispatchDelegate> — no reflection at any point. Prefer the strongly-typed overloads for maximum performance.

What Is Registered at Startup

What Runs per Request

This design ensures correct lifetime semantics: Singleton handlers are shared across all calls (safe for stateless handlers), Transient handlers get new instances per call (safe for handlers with DI dependencies), and Scoped handlers are shared within the HTTP request scope. Users can always override the auto-detected lifetime by re-registering after RegisterMediatorHandlers() — the last registration wins.

What This Means at Runtime

The result is that every Send(), Send(object), Publish(), and CreateStream() call at runtime uses precompiled dispatch tables with zero discovery overhead.