Table of Contents

Getting started

Install

For the simplest Microsoft dependency-injection setup:

dotnet add package Send0xx.Dispatcher.DependencyInjection

For source-generated registration and Native AOT, install instead:

dotnet add package Send0xx.Dispatcher.SourceGeneration
Important

Choose one implementation package. Both bring in the abstractions, runtime, and dependency injection integration they require. Source generation compares the two modes.

The rest of this page uses the reflection-based package.

Define a query and its handler

using Dispatcher;

public sealed record GetGreetingQuery(string Name) : IQuery<string>;

internal sealed class GetGreetingQueryHandler
    : IQueryHandler<GetGreetingQuery, string>
{
    public ValueTask<string> HandleAsync(
        GetGreetingQuery query,
        CancellationToken cancellationToken = default) =>
        ValueTask.FromResult($"Hello, {query.Name}!");
}

The handler is internal. Handlers never have to be public, under either registration mode.

Register Dispatcher

using Dispatcher.DependencyInjection;

builder.Services
    .AddDispatcher()
    .AddDispatcherHandlers(typeof(Program).Assembly);

AddDispatcher() registers infrastructure only and never scans assemblies implicitly. AddDispatcherHandlers() registers internal handler classes. Registering the same assembly more than once is safe.

Dispatch it

app.MapGet("/greetings/{name}", async (
    string name,
    IQueryDispatcher queries,
    CancellationToken cancellationToken) =>
{
    var greeting = await queries.QueryAsync(
        new GetGreetingQuery(name),
        cancellationToken);

    return Results.Ok(greeting);
});

Request /greetings/world to get "Hello, world!".

Dispatcher interfaces

Inject the narrowest one a class needs. They all resolve to the same implementation, so a narrow interface costs nothing at runtime.

Interface Method Dispatches
IQueryDispatcher QueryAsync Queries
ICommandDispatcher ExecuteAsync Commands, with or without a response
INotificationDispatcher PublishAsync Notifications
IDispatcher all of the above Anything, for classes that need more than one kind