RA.Utilities.Dispatcher
Version 10.0.1
Maintenance release updating the Microsoft.Extensions.* dependencies to the latest .NET 10 servicing patch. No API or behavior changes.
📝 Improvements
- Dependency updates:
Microsoft.Extensions.DependencyInjection.Abstractions10.0.12 → 10.0.13 andMicrosoft.Extensions.Logging.Abstractions10.0.12 → 10.0.13. Dependency versions are now managed as floating versions, so every release is built against — and ships with — the latest stable versions.
Version 10.0.0
Initial release of the RA.Utilities.Dispatcher package — the successor of RA.Utilities.Feature. It keeps the source-generated mediator, auto-registration, pipeline behaviors, and notification system, and returns to Result-based dispatch with a modern shape.
💥 Breaking Changes (from RA.Utilities.Feature 10.x)
- Package and namespace rename.
RA.Utilities.Feature→RA.Utilities.Dispatcher; every namespace moves fromRA.Utilities.Feature.*toRA.Utilities.Dispatcher.*.IMediator→IDispatcher,AddFeature→AddDispatcher,FeatureBuilder→DispatcherBuilder,NotificationFeatureBuilder→NotificationDispatcherBuilder, and generator diagnostics move fromFEAG001–FEAG010toDSAG001–DSAG010(same meanings). - Result-based dispatch redesign. Handlers return
ValueTask<Result<TResponse>>(ValueTask<Result>for void requests), andIDispatcher.SendreturnsValueTask<Result<TResponse>>/ValueTask<Result>. Expected failures are returned asResult.Failure(exception)instead of being thrown —ValidationBehaviorreturns a failed result containing aBadRequestExceptioninstead of throwing it. Truly exceptional cases still throw and propagate to the caller. INotificationHandlerreturns a result.HandleAsyncreturnsValueTask<Result>(wasTaskin Feature), andPublishaggregates handler failures into the returnedResult— a single exception when one handler fails, anAggregateExceptionwhen several fail.
✨ New Features
- Source-generated
IDispatcherimplementation (Mediator). The source generator emits the completeIDispatcherimplementation — the only dispatcher in the package — into every assembly referencing it, andAddMediator()registers it automatically.- Direct handler injection. The generated
Sendknows each message's handler, resolves it by concrete type, and calls it directly — no interface resolution, noGetServicesenumeration, and the call devirtualizes. - No delegate chain without behaviors. Requests with an empty pipeline invoke the handler directly — nothing is allocated for pipeline composition.
- Closed behaviors auto-register. Non-generic
IPipelineBehavior<,>/IPipelineBehavior<>/INotificationBehavior<>implementations are auto-registered under their interfaces (transient) and injected directly in deterministic order. Generic behaviors report the newDSAG010warning and remain available through explicitAddDecorationregistration. - Fast dictionary lookups for object dispatch.
Send(object)/Publish(object)usetypeofchains in small projects and switch to staticDictionary<Type, Delegate>lookups above a project-size threshold (more than 8 messages); unknown message types throwRA.Utilities.Dispatcher.Exceptions.HandlerNotFoundException.
- Direct handler injection. The generated
- Zero-configuration handler registration. A module initializer per assembly queues DI registrations (request handlers scoped, notification handlers transient) on
RA.Utilities.Dispatcher.Generated.HandlerRegistrations;AddMediator()applies them in one pass — plain handlers need no explicit registration at all. - Typed
PipelineContext<T>. Strongly-typed data carrier flowing through the entire pipeline — context-awareSend/Publishoverloads, context-aware delegate types, and default interface methods keep existing calls compiling unchanged. - Abstract
RequestHandlerbase classes.RequestHandler<TRequest>andRequestHandler<TRequest, TResponse>— pure passthroughs exposing one public abstractHandleAsyncplus a protected virtual context-aware overload. - Built-in behaviors.
LoggingBehavior(request logging at Information/Warning),ValidationBehavior(FluentValidation, returns a failed result carryingBadRequestException),NotificationLoggingBehavior,NotificationMetricsBehavior(allocation-free timestamp, warns over 500 ms), andNotificationRetryBehavior(configurable retries with incremental backoff). - C# 14 extension-block registration API.
AddMediator,AddDispatcher, andAddNotificationare implemented as C# 14 extension members — identical call sites, modern syntax. - Compile-time message diagnostics (category
RA.Utilities.Dispatcher.Generators):DSAG001–DSAG005(registration validity),DSAG006–DSAG009(message/handler contracts),DSAG010(generic behaviors) — ambiguous contracts, missing handlers, and unsupported shapes are reported at build time.
⚡ Performance
Benchmarks (MediatR handlers registered scoped, matching this package's lifetime; Apple M1, .NET 10.0.11, BenchmarkDotNet 0.15.8, MediatR 14.2.0, 2026-10-18):
| Scenario | MediatR | Generated Mediator (concrete) | Delta |
|---|---|---|---|
| Send, 0 behaviors | 283.2 ns / 608 B | 218.4 ns / 464 B | −23% time, −24% alloc |
| Send, 3 behaviors | 419.2 ns / 1136 B | 327.8 ns / 960 B | −22% time, −15% alloc |
| Send, void | 245.9 ns / 512 B | 215.2 ns / 432 B | −12% time, −16% alloc |
| Send, void + 3 behaviors | 419.6 ns / 1040 B | 317.8 ns / 928 B | −24% time, −11% alloc |
| Publish, 1 handler | 410.1 ns / 968 B | 295.2 ns / 672 B | −28% time, −31% alloc |
| Publish, 3 handlers | 639.3 ns / 1448 B | 390.2 ns / 992 B | −39% time, −31% alloc |
The concrete generated mediator is 12–39% faster than MediatR with 11–31% fewer allocations in every comparable shape, with the biggest wins on notification fan-out. The interface-typed IDispatcher path matches MediatR's speed on request dispatch while allocating less everywhere.
📖 Documentation
- New Docusaurus section under
nuget-packages/Application/Dispatcherfollowing the project's documentation template: package index, auto-registration guide, generated-mediator guide, benchmarks, migration guide (RA.Utilities.Feature10.x →RA.Utilities.Dispatcher10.0.0), troubleshooting & FAQ, and per-type reference pages forAbstractions,Behaviors,Builders,Exceptions,Extensions,Generated,Handlers, andModels. - New
RA.Utilities.Dispatcher.BenchmarksBenchmarkDotNet project comparing the generated mediator against MediatR 14.2 on identical send and publish scenarios, with per-scope resolution mirroring per-request semantics.