Dynamic Message Deserialization
Explanation · Applies to Brighter V10
Dynamic Deserialization Overview
Brighter supports dynamic type resolution, allowing you to route multiple message types through a single channel. Instead of determining the message type at compile-time through generic parameters, you can use content-based routing where the message type is determined at runtime from metadata.
This enables more flexible messaging patterns while maintaining type safety once the message type is resolved.
DataType Channel Pattern (Default)
By default, Brighter uses the DataType Channel pattern from Enterprise Integration Patterns. In this pattern, each channel carries messages of a single, known type.
DataType Channel Example
// DataType Channel - One type per subscription
var subscription = new KafkaSubscription<TaskCreated>(
new SubscriptionName("paramore.example.tasks"),
channelName: new ChannelName("task.created"),
routingKey: new RoutingKey("task.created"),
groupId: "task-processor",
timeOut: TimeSpan.FromMilliseconds(100)
);Characteristics:
Simple and straightforward
Type-safe at compile-time
One handler per channel
Recommended for most scenarios
Requires separate channel per message type
Cannot handle message type evolution on same channel
When to use DataType Channel:
You have distinct topics/queues for each message type
Message types are stable and don't evolve frequently
You want compile-time type safety
Simple producer-consumer patterns
This is Brighter's default and recommended approach for most scenarios.
Dynamic Message Deserialization
Dynamic message deserialization allows multiple message types on the same channel by resolving the type at runtime based on message metadata.
When to Use Dynamic Deserialization
Dynamic deserialization is useful when:
Multiple related message types share a single topic/queue
Message type evolution - new message types added to existing channels
CloudEvents-based routing - using the CloudEvents
typeattributeContent-based routing - routing decisions based on message content
Shared infrastructure - multiple teams publishing to common topics
How It Works
Instead of specifying the type via a generic parameter, you provide a getRequestType callback in your Subscription that examines the message and returns the appropriate type:
Performance Considerations
Dynamic message deserialization has a small performance overhead compared to DataType Channel:
Runtime Type Resolution
DataType Channel (Compile-Time):
Type known at compile-time via generic parameter
Message mapper pipeline pre-built
Minimal runtime overhead
Dynamic Deserialization (Runtime):
Type determined by executing callback function
Message mapper pipeline built on first use per type
Pipeline cached for subsequent messages of same type
Dynamic Deserialization Best Practices
1. Use CloudEvents Type for Routing
CloudEvents provides a standard, interoperable way to identify message types:
2. Provide Comprehensive Type Mappings
Handle all expected message types and provide a clear error for unmapped types:
3. Use Meaningful CloudEvents Types
Follow reverse-DNS naming for CloudEvents types:
See CloudEvents Support for more on CloudEvents type naming.
4. Consider DataType Channel First
Start with DataType Channel (one type per topic) unless you have a specific need for dynamic deserialization:
Only use dynamic when needed:
Multiple related types on same channel
Message evolution scenarios
CloudEvents-based integration
5. Cache Performance-Critical Paths
If performance is critical, pre-warm the pipeline cache:
6. Document Type Mappings
Document which CloudEvents types map to which Request types:
Comparison: DataType Channel vs Dynamic Deserialization
Type Resolution
Compile-time (generic)
Runtime (callback)
Performance
Fastest
Fast
Flexibility
One type per channel
Multiple types per channel
Type Safety
Compile-time
Runtime (after resolution)
Setup Complexity
Simple
Moderate
Message Evolution
Requires new channels
Same channel
CloudEvents Integration
Not needed
Natural fit
When to Use
Default, most scenarios
Multiple types, evolution
Dynamic Deserialization Error Handling
Handle unmapped message types gracefully:
Failed messages will go to the dead letter queue based on your failure handling configuration.
Further Reading
Routing Multiple Message Types - Routing several types down one channel
Cloud Events Support - Understanding CloudEvents in Brighter
Agreement Dispatcher - Dynamic handler selection
Default Message Mappers - Automatic message mapping
Routing - Message routing in Brighter
Dynamic Deserialization Sample Code
Full working examples can be found in the Brighter samples:
Dynamic Deserialization:
Brighter/samples/TaskQueue/- Examples using CloudEvents type routingMulti-type Channels:
Brighter/samples/MultiBus/- Multiple message types on shared infrastructure
Last updated
Was this helpful?
