CleanBusMediator 1.0.5
See the version list below for details.
dotnet add package CleanBusMediator --version 1.0.5
NuGet\Install-Package CleanBusMediator -Version 1.0.5
<PackageReference Include="CleanBusMediator" Version="1.0.5" />
<PackageVersion Include="CleanBusMediator" Version="1.0.5" />
<PackageReference Include="CleanBusMediator" />
paket add CleanBusMediator --version 1.0.5
#r "nuget: CleanBusMediator, 1.0.5"
#:package CleanBusMediator@1.0.5
#addin nuget:?package=CleanBusMediator&version=1.0.5
#tool nuget:?package=CleanBusMediator&version=1.0.5
๐ CleanBusMediator
CleanBusMediator is a modern, modular, and extensible Command Bus / Mediator framework for .NET.
It promotes a clean separation of responsibilities through Commands, Events, Streaming, Middleware Pipelines, Exception Handling, and more โ all with full support for dependency injection and testability.
Think of it as your lightweight, powerful message dispatcher โ without the magic.
๐ฆ Installation
Coming soon to NuGet:
dotnet add package CleanBusMediator
๐ง Quick Setup
1. Register CleanBusMediator in your DI container
CleanBusMediator supports multiple registration styles:
โค Standard (recommended for most apps)
builder.Services.CleanBusMediator(typeof(CreateUserHandler).Assembly);
This scans the specified assembly for:
- Command handlers
- Event handlers
- Stream handlers
- Middlewares
- Exception handlers
- Pre-/Post-processors
โค Fluent configuration (advanced)
builder.Services.CleanBusMediator(config =>
{
config.RegisterFromAssembly(typeof(CreateUserHandler).Assembly);
// Optional: add your own middleware behaviors
config.AddMiddleware(typeof(ResultValidationMiddleware<,>));
config.AddMiddleware(typeof(MyCustomLoggingBehavior<,>));
});
โค From Type (shorthand)
builder.Services.CleanBusMediator(typeof(CreateUserHandler));
โค Fallback: auto-discover all assemblies (use with caution)
builder.Services.CleanBusMediator();
โ ๏ธ This will scan all loaded assemblies in
AppDomain.CurrentDomain
.
Use only in small apps, tests, or single-project setups.
โ๏ธ Send Commands
Define a command
public class PingCommand : ICommand<string> { }
Handle the command
public class PingHandler : ICommandHandler<PingCommand, string>
{
public Task<string> Handle(PingCommand command, CancellationToken cancellationToken)
=> Task.FromResult("Pong!");
}
Dispatch it
var result = await dispatcher.Send(new PingCommand());
// result: "Pong!"
๐ข Publish Events
Define an event
public class OrderPlaced : IEvent
{
public Guid OrderId { get; set; }
}
Handle the event
public class SendConfirmationEmail : IEventHandler<OrderPlaced>
{
public Task Handle(OrderPlaced notification, CancellationToken cancellationToken)
{
Console.WriteLine($"Email sent for order {notification.OrderId}");
return Task.CompletedTask;
}
}
Publish it
await dispatcher.Publish(new OrderPlaced { OrderId = Guid.NewGuid() });
๐ Streaming Commands
Define a stream command
public class StreamNumbers : IStreamCommand<int>
{
public int Count { get; set; }
}
Handle it
public class StreamNumbersHandler : IStreamCommandHandler<StreamNumbers, int>
{
public async IAsyncEnumerable<int> Handle(StreamNumbers command, CancellationToken cancellationToken)
{
for (int i = 0; i < command.Count; i++)
{
yield return i;
await Task.Delay(100);
}
}
}
Consume the stream
await foreach (var number in dispatcher.Stream(new StreamNumbers { Count = 5 }))
{
Console.WriteLine(number);
}
๐งฉ Middleware Support
Define a middleware
public class LoggingMiddleware<TCommand, TResult> : ICommandMiddleware<TCommand, TResult>
where TCommand : ICommand<TResult>
{
public async Task<TResult> Handle(TCommand command, CancellationToken cancellationToken, CommandHandlerDelegate<TResult> next)
{
Console.WriteLine($"[Start] {typeof(TCommand).Name}");
var result = await next();
Console.WriteLine($"[End] {typeof(TCommand).Name}");
return result;
}
}
Registered automatically if in the scanned assembly.
๐ก๏ธ Exception Handling
Define an exception handler
public class PingExceptionHandler : ICommandExceptionHandler<PingCommand, string>
{
public Task<string> Handle(PingCommand command, Exception exception, CancellationToken cancellationToken)
{
return Task.FromResult("Recovered from error");
}
}
๐งช Pre- and Post-Processors
Pre-processor
public class ValidatePing : ICommandPreProcessor<PingCommand>
{
public Task Process(PingCommand command, CancellationToken cancellationToken)
{
Console.WriteLine("Pre-processing PingCommand");
return Task.CompletedTask;
}
}
Post-processor
public class LogPingResult : ICommandPostProcessor<PingCommand, string>
{
public Task Process(PingCommand command, string result, CancellationToken cancellationToken)
{
Console.WriteLine($"Post-processing result: {result}");
return Task.CompletedTask;
}
}
๐ Event Middleware
public class EventLoggingMiddleware<TEvent> : IEventMiddleware<TEvent>
where TEvent : IEvent
{
public async Task Handle(TEvent @event, CancellationToken cancellationToken, EventHandlerDelegate next)
{
Console.WriteLine($"[Event Start] {@event.GetType().Name}");
await next();
Console.WriteLine($"[Event End] {@event.GetType().Name}");
}
}
โก Parallel Event Publishing
Optional: run event handlers in parallel
await dispatcher.PublishParallel(new OrderPlaced { OrderId = Guid.NewGuid() });
๐งช Testing Support
Fake Dispatcher
var dispatcher = new FakeDispatcher
{
SendHandler = cmd => "FakeResult"
};
var result = await dispatcher.Send(new PingCommand());
Test Dispatcher (manual handler registration)
var testDispatcher = new TestDispatcher();
testDispatcher.RegisterHandler(new PingHandler());
var result = await testDispatcher.Send(new PingCommand());
๐ Retry Policies
Custom retry logic per command:
public class SimpleRetryPolicyProvider : IRetryPolicyProvider
{
public AsyncPolicy<TResult>? GetPolicy<TCommand, TResult>()
where TCommand : ICommand<TResult>
{
return Policy<TResult>
.Handle<Exception>()
.WaitAndRetryAsync(3, retry => TimeSpan.FromMilliseconds(200));
}
}
Used automatically via RetryMiddlewareFactory<,>
if registered.
๐ง Scoped Pipeline Builder
Need different middlewares per request? Use ScopedCommandPipelineBuilder
:
var scopedDispatcher = new Dispatcher(
type => scopedProvider.GetRequiredService(type),
new ScopedCommandPipelineBuilder(scopedProvider, defaultPipeline)
);
๐งฐ Built-in Middleware Available
- โ
LoggingMiddleware
- โ
ValidationMiddleware
(viaIValidator<>
) - โ
CachingMiddleware
(forICachableCommand
) - โ
RetryMiddleware
(viaIRetryPolicyProvider
)
๐งพ License
Licensed under the MIT License.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. 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 was computed. 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. |
-
net6.0
- No dependencies.
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.