Skip to content

george2006/TinyDispatcher

Repository files navigation

TinyDispatcher

TinyDispatcher is a small, compile-time oriented dispatcher for .NET.

It provides a predictable, explicit, and performant command/query dispatch core by moving:

  • handler discovery to build time
  • middleware pipeline composition to generated code (also build time)

...while keeping runtime execution simple and scope-friendly.

What you get

  • Compile-time handler discovery (no runtime scanning/reflection)
  • Generated pipelines (global middleware -> policy middleware -> per-command middleware -> handler)
  • Deterministic ordering and precedence rules (predictable output)
  • Explicit context (TContext) for command handlers
  • Multi-assembly composition with host-owned final pipeline generation
  • Pluggable context factory (delegate factory or DI registration)
  • Feature-friendly AppContext (optional IFeatureInitializer-based composition)
  • Source-generator diagnostics for invalid shapes/config (fail fast, no guessing)
  • Experimental context lanes in 1.2.0-alpha.* for module-owned contexts and typed dispatchers

Install

Stable release:

dotnet add package TinyDispatcher

Experimental multi-context / context-lane builds are published as 1.2.0-alpha.*. Use them only for evaluation and early feedback:

dotnet add package TinyDispatcher --version 1.2.0-alpha.1

1.1.x is the stable line. Context lanes are not part of the stable 1.1.x API.

Quick start

Define a command:

public sealed record CreateOrder(string OrderId) : ICommand;

Define a context-aware handler:

public sealed class CreateOrderHandler : ICommandHandler<CreateOrder, AppContext>
{
    public Task HandleAsync(CreateOrder command, AppContext ctx, CancellationToken ct = default)
        => Task.CompletedTask;
}

Register:

services.UseTinyDispatcher<AppContext>(tiny =>
{
    // optional: middleware, policies, features
});

For a custom context, register its factory in DI before bootstrapping:

services.AddScoped<IContextFactory<MyContext>, MyContextFactory>();

services.UseTinyDispatcher<MyContext>(tiny =>
{
    // optional: middleware, policies, features
});

Dispatch:

await dispatcher.DispatchAsync(new CreateOrder("123"), ct);

Multi-assembly composition

TinyDispatcher supports a modular setup where:

  • handlers can live in referenced class libraries
  • middleware and policies can also live outside the host assembly
  • contributing assemblies publish structured compile-time metadata
  • the host remains the sole final composer of pipelines

This keeps the runtime simple while letting the generator build final pipelines for the full command universe visible to the host.

Experimental: context lanes

Context lanes are available in 1.2.0-alpha.*. They allow independent, typed dispatcher pipelines inside the same application, where each lane has its own context, handlers, middleware and policies.

Use one lane by default. Add more lanes only when the application has real execution-context or pipeline differences.

See Multi-Lane Dispatching for the alpha documentation and Orders/Payments sample pointers.

Documentation

When to use

TinyDispatcher is a good fit when you want:

  • explicit execution flow you can read and debug
  • deterministic middleware precedence
  • compile-time discovery (no runtime scanning)
  • a small, focused dispatch core rather than a full framework
  • aot friendly.
  • microservices, minimal Api and Azure functions.

Test Coverage & Hardening

TinyDispatcher includes a comprehensive automated test suite covering both the runtime dispatcher and the Roslyn source generator.

Current coverage (March 2026):

Component Line Coverage Branch Coverage
Overall ~89% ~76%
Runtime (TinyDispatcher) ~84% ~68%
Source Generator (TinyDispatcher.SourceGen) ~90% ~77%

Critical runtime infrastructure is fully covered, including:

  • AppContext
  • FeatureCollection
  • DefaultAppContextFactory
  • ServiceCollectionExtensions
  • TinyBootstrap

These components form the core execution and configuration model of TinyDispatcher.

Hardening Sessions

Leading up after the first stable release, the project is undergoing a short series of hardening sessions focused on strengthening runtime guarantees and improving branch coverage.

These sessions concentrate on:

  • improving branch coverage for the dispatcher execution paths
  • validating middleware and policy registration behavior
  • verifying cancellation propagation through the dispatcher pipeline
  • testing error scenarios and diagnostics generated by the source generator
  • increasing coverage for generator validation paths

All tests focus on observable behavior rather than internal implementation details, ensuring the dispatcher can evolve safely without breaking public guarantees.

The goal is to keep TinyDispatcher:

  • predictable
  • explicit
  • well-tested
  • safe to evolve

Samples

The repository contains runnable samples under samples/, including:

  • ASP.NET and custom context setups
  • context factory and closed-context middleware examples
  • a multi-project sample showing cross-assembly handler and pipeline composition

Packages

 
 
 

Contributors

Languages