TurboMediator
Integrations

Source Generator

How the TurboMediator source generator works and its build-time diagnostics

TurboMediator uses a Roslyn Incremental Source Generator to produce compile-time optimized code. This is the core of the library's performance advantage.

What Gets Generated

The source generator produces:

  1. Mediator class — The concrete IMediator implementation with switch-expression dispatch for each message type
  2. ExecuteWithPipeline method — Resolves pre-processors, pipeline behaviors, exception handlers, and post-processors from DI and chains them
  3. AddTurboMediator() extension — DI registration that wires all discovered handlers

Example Generated Code

For a project with PingRequest and GetUserQuery:

// Generated by TurboMediator Source Generator
internal sealed class Mediator : IMediator
{
    private readonly IServiceProvider _serviceProvider;

    public Mediator(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public ValueTask<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken ct)
    {
        return request switch
        {
            PingRequest msg => ExecuteWithPipeline<PingRequest, string>(msg, ct),
            _ => throw new InvalidOperationException($"No handler for {request.GetType().Name}")
        };
    }

    public ValueTask<TResponse> Send<TResponse>(IQuery<TResponse> query, CancellationToken ct)
    {
        return query switch
        {
            GetUserQuery msg => ExecuteWithPipeline<GetUserQuery, User?>(msg, ct),
            _ => throw new InvalidOperationException($"No handler for {query.GetType().Name}")
        };
    }

    // ... similar for Commands and Notifications
}

No Reflection

The key benefit is that dispatch is a compile-time switch expression — no Dictionary<Type, Handler> lookups, no Activator.CreateInstance, no MethodInfo.Invoke. This makes it:

  • Faster than reflection-based mediators
  • Compatible with Native AOT publishing
  • Fully trimmable by the .NET linker

Build-Time Diagnostics

The source generator emits diagnostics during compilation:

CodeSeverityDescription
TURBO001WarningNo handler found for message type
TURBO002ErrorMultiple handlers for the same message type
TURBO003ErrorInvalid handler signature
TURBO004ErrorResponse type mismatch between message and handler
TURBO005WarningHandler class is abstract (cannot be instantiated)
TURBO006WarningNo stream handler found for stream message
TURBO007ErrorMultiple stream handlers for the same message
TURBO008ErrorHandler class must be public
TURBO009InfoDuplicate notification handler detected

Example Build Errors

error TURBO002: Multiple handlers found for 'GetUserQuery': GetUserHandler, AnotherGetUserHandler
error TURBO008: Handler 'InternalHandler' must be public to be discovered by TurboMediator
warning TURBO001: No handler found for message 'OrphanedCommand'

How It Works Internally

  1. Parser Phase: Scans the syntax tree for:

    • Classes implementing handler interfaces (IRequestHandler, ICommandHandler, IQueryHandler, INotificationHandler, streaming variants)
    • Types implementing message interfaces (IRequest, ICommand, IQuery, INotification, streaming variants)
  2. Validation Phase: Checks for:

    • Missing handlers
    • Duplicate handlers
    • Signature mismatches
    • Accessibility (public)
  3. Emission Phase: Generates:

    • Mediator class with switch-expression routing
    • Pipeline execution with DI-resolved behaviors
    • AddTurboMediator() service collection extension

On this page