ProDispatch is a lightweight, in-process dispatcher inspired by MediatR. It supports commands, queries, notifications, and pluggable pipeline behaviors without requiring a heavy dependency injection container.
- MediatR-Compatible API: Use
IRequest/IRequestHandlerfor seamless migration from MediatR - CQRS Support: Dedicated
ICommand/IQueryinterfaces with their respective handlers - Flexible Pipeline Behaviors: Scope behaviors to commands-only, queries-only, or all requests
- Notifications: Fan-out to multiple handlers with
INotification - Native Dependency Injection: Uses
IServiceCollectionandIServiceProviderthrough Microsoft.Extensions.DependencyInjection.Abstractions - Fully Tested: Comprehensive test coverage with samples, integration tests, and benchmarks
- Build the solution:
dotnet build ProDispatch.slnx
- Run the sample console app:
dotnet run --project samples/ProDispatch.Examples.Console/ProDispatch.Examples.Console.csproj
- Run tests:
dotnet test ProDispatch.slnx
- Run benchmarks:
dotnet run -c Release --project benchmarks/ProDispatch.Benchmarks/ProDispatch.Benchmarks.csproj
- Library: src/ProDispatch
- Sample: samples/ProDispatch.Examples.Console
- Tests: tests/ProDispatch.Tests and tests/ProDispatch.IntegrationTests
- Benchmarks: benchmarks/ProDispatch.Benchmarks
- Docs: docs (see getting-started, advanced-usage, performance, migration-from-mediatr)
using Microsoft.Extensions.DependencyInjection;
using ProDispatch.Abstractions.Dispatcher;
services.AddProDispatch(cfg =>
{
cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
});Inject IDispatcher into application services or Minimal API endpoints. Request, command, query, and notification handlers are discovered automatically and registered as transient services. Application dependencies are registered normally in IServiceCollection and resolved from the caller's scope.
Pipeline behaviors are opt-in and run first-added outermost:
services.AddProDispatch(cfg =>
{
cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
cfg.AddOpenBehavior(typeof(LoggingBehavior<,>));
cfg.AddOpenBehavior(typeof(ValidationBehavior<,>));
});LoggingBehavior and ValidationBehavior are examples in the sample projects, not built-in library services.
// Define a request
public record GetUserQuery(Guid Id) : IRequest<User>;
// Define a handler
public class GetUserQueryHandler : IRequestHandler<GetUserQuery, User>
{
public Task<User> HandleAsync(GetUserQuery request, CancellationToken cancellationToken)
{
// ... fetch user
}
}
// Send the request
var user = await dispatcher.Send(new GetUserQuery(userId));// Commands
public record CreateUserCommand(string Name) : ICommand<Guid>;
public class CreateUserHandler : ICommandHandler<CreateUserCommand, Guid> { }
// Queries
public record GetUserByIdQuery(Guid Id) : IQuery<User>;
public class GetUserByIdHandler : IQueryHandler<GetUserByIdQuery, User> { }
// Usage
var userId = await dispatcher.SendAsync(new CreateUserCommand("Alice"));
var user = await dispatcher.SendAsync(new GetUserByIdQuery(userId));// Apply to all requests
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> { }
// Apply only to commands
public class TransactionBehavior<TRequest, TResponse> :
IPipelineBehavior<TRequest, TResponse>,
ICommandPipelineBehavior { }
// Apply only to queries
public class CachingBehavior<TRequest, TResponse> :
IPipelineBehavior<TRequest, TResponse>,
IQueryPipelineBehavior { }See docs/getting-started.md for a full walkthrough and docs/advanced-usage.md for customization tips.
- GitHub Actions build, test, and Sonar analysis via .github/workflows/ci.yml
- Security scanning via .github/workflows/codeql.yml
- NuGet packaging/release automation via .github/workflows/release.yml
Please read CONTRIBUTING.md and CODE_OF_CONDUCT.md before opening issues or pull requests. Suggestions and improvements are welcome.