3.7 KiB
3.7 KiB
Command Registration
How to register command handlers in dependency injection.
Basic Registration
Command with Result
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
This registers:
- Handler as
ICommandHandler<CreateUserCommand, int> - Metadata for endpoint discovery
- Scoped lifetime (default)
Command without Result
builder.Services.AddCommand<DeleteUserCommand, DeleteUserCommandHandler>();
Registration with Validator
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler, CreateUserCommandValidator>();
This registers:
- Handler
- Validator as
IValidator<CreateUserCommand> - Metadata
Registration with Workflow
builder.Services.AddCommandWithWorkflow<CreateUserCommand, int, UserWorkflow, CreateUserCommandHandler>();
For event-emitting commands.
Service Lifetimes
Scoped (Default - Recommended)
services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
// Handler is Scoped
Characteristics:
- One instance per request
- Can inject DbContext
- Disposed after request
Custom Lifetime
// Transient
services.AddTransient<ICommandHandler<CreateUserCommand, int>, CreateUserCommandHandler>();
// Singleton (not recommended - can't inject DbContext)
services.AddSingleton<ICommandHandler<CreateUserCommand, int>, CreateUserCommandHandler>();
Bulk Registration
Extension Methods
// Extensions/ServiceCollectionExtensions.cs
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddUserCommands(this IServiceCollection services)
{
services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler, CreateUserCommandValidator>();
services.AddCommand<UpdateUserCommand, UpdateUserCommandHandler, UpdateUserCommandValidator>();
services.AddCommand<DeleteUserCommand, DeleteUserCommandHandler>();
return services;
}
public static IServiceCollection AddOrderCommands(this IServiceCollection services)
{
services.AddCommand<PlaceOrderCommand, int, PlaceOrderCommandHandler>();
services.AddCommand<CancelOrderCommand, CancelOrderCommandHandler>();
return services;
}
}
// Usage in Program.cs
builder.Services.AddUserCommands();
builder.Services.AddOrderCommands();
Module Pattern
public interface IModule
{
void RegisterServices(IServiceCollection services);
}
public class UserModule : IModule
{
public void RegisterServices(IServiceCollection services)
{
// Commands
services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
services.AddCommand<UpdateUserCommand, UpdateUserCommandHandler>();
// Queries
services.AddQuery<GetUserQuery, UserDto, GetUserQueryHandler>();
// Services
services.AddScoped<IUserRepository, UserRepository>();
}
}
// Auto-register all modules
var modules = typeof(Program).Assembly
.GetTypes()
.Where(t => typeof(IModule).IsAssignableFrom(t) && !t.IsInterface)
.Select(Activator.CreateInstance)
.Cast<IModule>();
foreach (var module in modules)
{
module.RegisterServices(builder.Services);
}
Organizing Registrations
By Feature
Program.cs
Extensions/
UserServiceRegistration.cs
OrderServiceRegistration.cs
ProductServiceRegistration.cs
By Layer
Program.cs
Extensions/
CommandRegistration.cs
QueryRegistration.cs
RepositoryRegistration.cs
See Also
- Dependency Injection - DI patterns
- Modular Solution Structure