For the complete documentation index, see llms.txt. This page is also available as Markdown.

Agreement Dispatcher

How-to · Applies to Brighter V10

Agreement Dispatcher Overview

The Agreement Dispatcher is a pattern for routing requests to handlers dynamically based on the request's content or context, rather than using a fixed type-to-handler mapping. This pattern, described by Martin Fowler in Patterns of Enterprise Application Architecture, enables flexible routing logic that can change based on business rules, time, geography, or other runtime conditions.

Brighter supports an Agreement Dispatcher, allowing you to register a lambda function that determines which handler(s) should process a request at runtime.

Registration Syntax

Basic Registration

registry.Register<TRequest>(
    routingFunc: (request, context) => { /* return handler types */ },
    handlerTypes: [typeof(Handler1), typeof(Handler2), ...]
);

Parameters:

  • routingFunc: Lambda that takes IRequest and IRequestContext, returns List<Type> of handlers

  • handlerTypes: Array of all possible handler types (for DI registration)

Accessing Request Content

The routing function receives IRequest, which you must cast to your specific type:

Why the cast? The registry supports multiple request types, so the lambda signature uses IRequest. You need to cast to access type-specific properties.

Accessing Request Context

The IRequestContext provides additional information:

Returning Multiple Handlers

Agreement Dispatcher can return multiple handlers, but it must still obey the rule that Send expects a single handler and Publish can have zero-to-many handlers. If you return multiple handlers in a Send request pipeline, Brighter will throw an exception.

Synchronous and Asynchronous Registration

Agreement Dispatcher supports both sync and async handlers:

Synchronous Registration

Asynchronous Registration

Note: The routing lambda itself is always synchronous. Only the handler execution is async when using RegisterAsync.

Integration with Dynamic Message Deserialization

Agreement Dispatcher can be combined with Dynamic Message Deserialization for two-level routing:

This provides powerful, flexible routing:

  1. CloudEvents type determines the Request type

  2. Request content determines the Handler

Complete Example

Here's a complete example showing Agreement Dispatcher with multiple routing strategies:

Agreement Dispatcher Best Practices

1. Keep Routing Logic Simple

Routing lambdas should be fast and deterministic:

2. Provide Clear Error Messages

Handle unexpected cases gracefully:

3. Document Routing Rules

Document the routing logic for maintainability:

4. Use Standard Routing When Possible

Only use Agreement Dispatcher when you need dynamic routing:

5. List All Possible Handlers

Always provide the complete list of handler types:

Agreement Dispatcher Troubleshooting

Handler Not Found Error

Problem: Runtime error saying handler type cannot be resolved.

Cause: Handler type not in the handler types array.

Solution: Add the handler to the array:

AutoFromAssemblies Conflicts

Problem: Agreement dispatcher routes not working with AutoFromAssemblies().

Cause: AutoFromAssemblies() creates fixed mappings.

Solution: Use explicit .Handlers() registration:

Further Reading

Agreement Dispatcher Sample Code

Full working examples can be found in the Brighter samples:

  • Agreement Dispatcher: Brighter/samples/WebAPI/ - Examples of dynamic handler selection

  • Multi-handler: Various samples showing handler pipeline composition

Last updated

Was this helpful?