DSoftStudio Mediator

← Back to Documentation

Installation

Core Package

dotnet add package DSoftStudio.Mediator

Companion Packages

dotnet add package DSoftStudio.Mediator.OpenTelemetry      # Distributed tracing + metrics
dotnet add package DSoftStudio.Mediator.FluentValidation    # Request validation
dotnet add package DSoftStudio.Mediator.HybridCache         # Query caching

Requirements

Strong Naming

All assemblies are signed with PublicKeyToken=6c7e753832e8eb05 (v1.2.0+). This enables:

Cross-Project Handler Discovery

AddMediator(configure) (and the lower-level RegisterMediatorHandlers()) automatically discovers all handler implementations (IRequestHandler<,>, INotificationHandler<>, IStreamRequestHandler<,>, and their CQRS aliases ICommandHandler<,>, IQueryHandler<,>) across all referenced projects — no manual registration required.

Each project that references DSoftStudio.Mediator emits [assembly: MediatorHandlerRegistration] attributes at compile time. Downstream projects read these attributes to build the complete handler registry, without runtime reflection or assembly scanning.

This works seamlessly with Clean Architecture setups:

Host/API  →  references Application & Infrastructure
              └─ AddMediator(configure) discovers handlers from both

Tip: every project that defines handlers should reference the DSoftStudio.Mediator NuGet package so the source generator can run and emit the assembly attributes (Phase 1 — fast path). However, projects that only reference DSoftStudio.Mediator.Abstractions are still discovered automatically via type-based scanning (Phase 2 — fallback). The host project that calls AddMediator(configure) must always reference DSoftStudio.Mediator.

Required Namespaces

The mediator uses two namespaces — which ones you need depends on the project layer:

Project layer Namespace Purpose
Domain / Application DSoftStudio.Mediator.Abstractions ISender, IMediator, IRequest<T>, ICommand<T>, INotification, handler interfaces
Host / API DSoftStudio.Mediator AddMediator() DI extensions, typed Send() / CreateStream() extension methods

In your host/startup project (where you call AddMediator(configure) and inject ISender), you typically need both:

using DSoftStudio.Mediator.Abstractions; // ISender, IMediator, ICommand<T>, IRequest<T>, etc.
using DSoftStudio.Mediator;              // Typed Send() / CreateStream() extensions + AddMediator() DI extensions

In domain or application layer projects (where you define requests, handlers, and inject ISender), only the abstractions namespace is required:

using DSoftStudio.Mediator.Abstractions;

Why the second namespace matters in the host project: the source generator emits typed extension methods (e.g. Send(MyCommand)) in the DSoftStudio.Mediator namespace. Without this using, the compiler falls back to the generic ISender.Send<TRequest, TResponse>() and reports CS0411 because it cannot infer both type arguments.

Tip: add the namespaces you need to a GlobalUsings.cs file so every file in the project picks them up automatically:

// GlobalUsings.cs
global using DSoftStudio.Mediator;
global using DSoftStudio.Mediator.Abstractions;

Native AOT and Trimming

Both packages ship with IsAotCompatible and IsTrimmable enabled. The hot execution path uses no reflection, no MakeGenericType, no Expression.Compile, and no dynamic method generation — all handler discovery and dispatch wiring are performed at compile time by Roslyn source generators.

This makes the mediator suitable for:

The Publish(object) and Send(object) overloads (runtime-typed dispatch) are also AOT-safe — they use compile-time generated FrozenDictionary<Type, DispatchDelegate> dispatch tables populated by the source generator, with no MakeGenericType at runtime.

See Also