SwartBerg.Mediator
2.0.10
dotnet add package SwartBerg.Mediator --version 2.0.10
NuGet\Install-Package SwartBerg.Mediator -Version 2.0.10
<PackageReference Include="SwartBerg.Mediator" Version="2.0.10" />
<PackageVersion Include="SwartBerg.Mediator" Version="2.0.10" />
<PackageReference Include="SwartBerg.Mediator" />
paket add SwartBerg.Mediator --version 2.0.10
#r "nuget: SwartBerg.Mediator, 2.0.10"
#:package SwartBerg.Mediator@2.0.10
#addin nuget:?package=SwartBerg.Mediator&version=2.0.10
#tool nuget:?package=SwartBerg.Mediator&version=2.0.10
SwartBerg.Mediator
A mediator implementation for with background processing and notification persistence.
Inspired by MediatR, this library was created as a free alternative with similar patterns but includes built-in persistence and background processing.
The name "SwartBerg" means "Black Mountain" in Afrikaans, it is a combination of my surname and my wife's maiden name. If you like to thank me for the library buy me a coffee. Link is at the bottom of this readme.
Features
- High Performance: Precompiled generic delegates (no runtime expression compilation)
- Background Processing: Non-blocking notification dispatch with worker pool
- Pipeline Behaviors: Plug-in cross-cutting concerns
- Configurable Persistence: Pluggable store & serializer
- Retry Logic: Exponential backoff with precomputed delays
- Modern Async Patterns: Optional global ConfigureAwait(false)
- Lightweight: Low allocations, minimal deps
Requirements
- .NET 8.0 or later
- Works with:
- .NET 8+ applications
- .NET MAUI applications
- Blazor applications
- ASP.NET 8+ Core applications
- Console applications
- WPF applications
- WinForms applications
Installation
Package Manager Console
Install-Package SwartBerg.Mediator
.NET CLI
dotnet add package SwartBerg.Mediator
PackageReference
<PackageReference Include="SwartBerg.Mediator" Version="2.0.3" />
Quick Start
1. Define your requests and handlers
public class GetUserQuery : IRequest<User>
{
public int UserId { get; set; }
}
public class GetUserHandler : IRequestHandler<GetUserQuery, User>
{
public Task<User> Handle(GetUserQuery request, CancellationToken cancellationToken)
{
return Task.FromResult(new User { Id = request.UserId, Name = "John Doe" });
}
}
public class CreateUserCommand : IRequest
{
public string Name { get; set; }
public string Email { get; set; }
}
public class CreateUserHandler : IRequestHandler<CreateUserCommand>
{
public Task Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
public class UserCreatedNotification : INotification
{
public int UserId { get; set; }
public string Name { get; set; }
}
public class SendWelcomeEmailHandler : INotificationHandler<UserCreatedNotification>
{
public Task Handle(UserCreatedNotification notification, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
2. Register services
builder.Services.AddMediator(typeof(Program).Assembly);
3. Use the mediator
public class UserController : ControllerBase
{
private readonly IMediator _mediator;
public UserController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet("{id}")]
public async Task<User> GetUser(int id)
{
return await _mediator.Send(new GetUserQuery { UserId = id });
}
[HttpPost]
public async Task CreateUser(CreateUserCommand command)
{
await _mediator.Send(command);
await _mediator.Publish(new UserCreatedNotification { UserId = 1, Name = command.Name });
}
}
Advanced Configuration
Pipeline Behaviors
public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
ValidateRequest(request);
return await next();
}
}
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
Custom Persistence
services.AddSingleton<INotificationPersistence, RedisNotificationPersistence>();
services.AddSingleton<INotificationPersistence, SqlServerNotificationPersistence>();
services.AddMediator(options => options.EnablePersistence = false, typeof(Program).Assembly);
Configuration Options
services.AddMediator(options =>
{
options.NotificationWorkerCount = 4;
options.EnablePersistence = true;
options.ProcessingInterval = TimeSpan.FromSeconds(30);
options.ProcessingBatchSize = 50;
options.MaxRetryAttempts = 3;
options.InitialRetryDelay = TimeSpan.FromMinutes(2);
options.RetryDelayMultiplier = 2.0;
options.CleanupRetentionPeriod = TimeSpan.FromHours(24);
options.CleanupInterval = TimeSpan.FromHours(1);
// options.UseConfigureAwaitGlobally = false; // only if you need sync ctx
}, typeof(Program).Assembly);
Architecture
Channel-first with optional persistence:
- In-memory channel dispatch
- Optional persistence backup
- Periodic recovery loop
- Periodic cleanup loop
Publish() → Channel → Background Workers
↘
Persist() → Storage
↘
Recovery → Channel
Performance improvements in recent updates:
- Cached concrete handler factories for faster scoped resolution when dispatching notifications.
- Notification handler type caching to avoid holding root-scoped instances and reduce allocations.
- Delayed serialization during Publish to avoid unnecessary serialization when persistence is disabled or fails.
## Testing
```bash
dotnet test
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Add changes + tests
- Run benchmarks
- Commit:
git commit -m 'Add amazing feature' - Push:
git push origin feature/amazing-feature - Open PR
License
MIT License - see LICENSE.
Support
Open issues for bugs or features. Provide clear reproduction steps.
Appreciation (Optional)
Free forever. If it helps you and you want to buy a coffee:
**Always free. No premium features, no paid support.**Always free.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 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
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
-
net8.0
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
-
net9.0
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.10 | 132 | 2/19/2026 |
| 2.0.9 | 90 | 2/18/2026 |
| 2.0.8 | 141 | 2/12/2026 |
| 2.0.7 | 115 | 2/7/2026 |
| 2.0.6 | 128 | 2/1/2026 |
| 2.0.5 | 98 | 2/1/2026 |
| 2.0.4 | 99 | 1/31/2026 |
| 2.0.3 | 100 | 1/28/2026 |
| 2.0.2 | 130 | 1/23/2026 |
| 2.0.1 | 99 | 1/22/2026 |
| 2.0.0 | 159 | 1/9/2026 |
| 1.0.5 | 245 | 11/24/2025 |
| 1.0.4 | 426 | 11/20/2025 |
| 1.0.3 | 420 | 11/19/2025 |
| 1.0.2 | 419 | 11/19/2025 |
| 1.0.1 | 186 | 10/31/2025 |
| 1.0.0 | 236 | 9/20/2025 |
| 0.1.4-ci0010 | 215 | 9/20/2025 |
Version 2.0.0: Added support for .NET 10. High-performance mediator with compiled expressions, background notifications, pipeline behaviors, file-based persistence with retry logic, and built-in ConfigureAwait(false) for automatic deadlock prevention. Safe by default for all application types. Supports .NET 9 and .NET 10.