ChannelMediator.AzureBus
1.0.8
dotnet add package ChannelMediator.AzureBus --version 1.0.8
NuGet\Install-Package ChannelMediator.AzureBus -Version 1.0.8
<PackageReference Include="ChannelMediator.AzureBus" Version="1.0.8" />
<PackageVersion Include="ChannelMediator.AzureBus" Version="1.0.8" />
<PackageReference Include="ChannelMediator.AzureBus" />
paket add ChannelMediator.AzureBus --version 1.0.8
#r "nuget: ChannelMediator.AzureBus, 1.0.8"
#:package ChannelMediator.AzureBus@1.0.8
#addin nuget:?package=ChannelMediator.AzureBus&version=1.0.8
#tool nuget:?package=ChannelMediator.AzureBus&version=1.0.8
๐ ChannelMediator
A modern, high-performance mediator for .NET, built on System.Threading.Channels, with full MediatR compatibility.
โจ Features
- โ
MediatR Compatible - Familiar API (
Send/Publish) - โ Channel-Based - Asynchronous processing with natural backpressure
- โ Pipeline Behaviors - Global AND specific
- โ Parallel Notifications - Sequential or parallel broadcasting
- โ High Performance - Channel-based with modern optimizations
- โ Azure Service Bus - Distributed messaging with queues and topics
- โ .NET 10 - Modern code with C# 14
๐ฆ Installation
# Package (coming soon)
dotnet add package ChannelMediator
# Or local reference
<ProjectReference Include="..\ChannelMediator\ChannelMediator.csproj" />
๐ฏ Quick Start
Configuration
using ChannelMediator;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
var services = new ServiceCollection();
// Register the mediator
services.AddChannelMediator(
config => config.Strategy = NotificationPublishStrategy.Parallel,
Assembly.GetExecutingAssembly());
var provider = services.BuildServiceProvider();
var mediator = provider.GetRequiredService<IMediator>();
Define a Request
// Request
public record AddToCartRequest(string ProductCode) : IRequest<CartItem>;
// Response
public record CartItem(string ProductCode, int Quantity, decimal Total);
// Handler
public class AddToCartHandler : IRequestHandler<AddToCartRequest, CartItem>
{
public async Task<CartItem> Handle(
AddToCartRequest request,
CancellationToken cancellationToken)
{
// Business logic
return new CartItem(request.ProductCode, 1, 19.99m);
}
}
Usage
var cart = await mediator.Send(new AddToCartRequest("ABC123"));
Notifications
// Notification
public record ProductAddedNotification(string ProductCode, int Quantity) : INotification;
// Handlers (multiple handlers supported)
public class LogHandler : INotificationHandler<ProductAddedNotification>
{
public Task Handle(ProductAddedNotification notification, CancellationToken ct)
{
Console.WriteLine($"LOG: {notification.ProductCode}");
return Task.CompletedTask;
}
}
public class EmailHandler : INotificationHandler<ProductAddedNotification>
{
public async Task Handle(ProductAddedNotification notification, CancellationToken ct)
{
await SendEmailAsync(notification.ProductCode);
}
}
// Publish notification to all handlers
await mediator.Publish(new ProductAddedNotification("ABC123", 1));
๐ญ Pipeline Behaviors
Global Behaviors (for ALL requests)
public class LoggingBehavior<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>, IPipelineBehavior
where TRequest : IRequest<TResponse>
{
public async ValueTask<TResponse> HandleAsync(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
Console.WriteLine($"Before: {typeof(TRequest).Name}");
var response = await next();
Console.WriteLine($"After: {typeof(TRequest).Name}");
return response;
}
}
// Registration
services.AddOpenPipelineBehavior(typeof(LoggingBehavior<,>));
services.AddOpenPipelineBehavior(typeof(PerformanceMonitoringBehavior<,>));
Specific Behaviors (for a specific request type)
public class ValidationBehavior<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
public async ValueTask<TResponse> HandleAsync(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
// Specific validation
if (request is AddToCartRequest { ProductCode: null or "" })
throw new ArgumentException("ProductCode required");
return await next();
}
}
// Registration
services.AddPipelineBehavior<AddToCartRequest, CartItem, ValidationBehavior<AddToCartRequest, CartItem>>();
๐ Available APIs
| Method | Return Type | Description |
|---|---|---|
Send<TResponse>(IRequest<TResponse>, CancellationToken) |
Task<TResponse> |
Sends a request to a single handler and returns the response |
Send(IRequest, CancellationToken) |
Task |
Sends a request without response (command) |
Send(object, CancellationToken) |
Task<object?> |
Sends a request resolved at runtime |
Publish<TNotification>(TNotification, CancellationToken) |
Task |
Publishes a notification to multiple handlers |
Publish(object, CancellationToken) |
Task |
Publishes a notification resolved at runtime |
๐ Documentation
- ๐ Azure Service Bus Integration
- ๐ MediatR Compatibility
- ๐ญ Pipeline Behaviors
- ๐ Sequence Diagram
๐๏ธ Architecture
Client
โ
IMediator (Send / Publish)
โ
Channel (async queue)
โ
RequestHandlerWrapper
โ
Pipeline Behaviors (chain)
โโ Global Behavior 1
โโ Global Behavior 2
โโ Specific Behavior 1
โโ Request Handler (business logic)
๐ Azure Service Bus Integration
In a microservice architecture, a single process cannot handle all requests. You need to distribute workloads across multiple consumer instances and decouple services through asynchronous messaging.
ChannelMediator.AzureBus extends the mediator with two extension methods that transparently route messages through Azure Service Bus:
mediator.Notify(notification)โ Publishes to a Topic (fan-out to all subscribers)mediator.EnqueueRequest(request)โ Enqueues to a Queue (competing consumers, only one processes each message)
var mediator = app.Services.GetRequiredService<IMediator>();
// Fan-out notification to all subscriber services
await mediator.Notify(new ProductAddedNotification("SKU-001", 5, 49.95m));
// Enqueue a request for competing consumer processing
await mediator.EnqueueRequest(new MyRequest("process-order-42"));
Supports Live mode (real Azure Service Bus) and Mock mode (in-process for local development). Queues, topics, and subscriptions are created automatically on first use.
๐ฏ Use Cases
Perfect for:
- โ High-load applications (backpressure)
- โ Microservices with CQRS patterns
- โ Migration from MediatR (drop-in replacement)
- โ REST / gRPC APIs with complex orchestration
- โ Event-driven architectures
Examples:
- E-commerce: Orders, cart, checkout
- CMS: Publishing, workflow, notifications
- IoT: Telemetry, commands, events
- Finance: Transactions, audit, reporting
โ๏ธ Advanced Configuration
Parallel Notifications
services.AddChannelMediator(config =>
config.Strategy = NotificationPublishStrategy.Parallel);
// All handlers execute in parallel with Task.WhenAll
await mediator.Publish(notification);
Sequential Notifications
services.AddChannelMediator(config =>
config.Strategy = NotificationPublishStrategy.Sequential);
// Handlers execute one after another
await mediator.Publish(notification);
๐งช Tests
[Fact]
public async Task Should_Handle_Request()
{
// Arrange
var services = new ServiceCollection();
services.AddChannelMediator(Assembly.GetExecutingAssembly());
var provider = services.BuildServiceProvider();
var mediator = provider.GetRequiredService<IMediator>();
// Act
var result = await mediator.Send(new AddToCartRequest("TEST"));
// Assert
Assert.NotNull(result);
Assert.Equal("TEST", result.ProductCode);
}
๐ง Compatibility
- .NET 10 (can be back-ported to .NET 8)
- C# 14 (can be adapted for C# 12)
- Microsoft.Extensions.DependencyInjection 9.0+
๐ License
MIT (to be defined)
๐ฅ Contributing
Contributions are welcome! Open an issue or a PR.
๐ Inspirations
- MediatR - The original and still excellent
- System.Threading.Channels - The foundation of our implementation
โญ Why ChannelMediator?
- Performance - Channel-based asynchronous processing
- Flexibility - MediatR-compatible API with powerful extensions
- Modern - .NET 10, C# 14, modern patterns
- Powerful - Global behaviors, parallel notifications
- Familiar - MediatR compatible, easy migration
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Azure.Messaging.ServiceBus (>= 7.20.1)
- ChannelMediator (>= 1.0.10)
- Microsoft.Extensions.DependencyInjection (>= 10.0.5)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.5)
-
net9.0
- Azure.Messaging.ServiceBus (>= 7.20.1)
- ChannelMediator (>= 1.0.10)
- Microsoft.Extensions.DependencyInjection (>= 10.0.5)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.