dotnet-cqrs/docs/core-features/commands/command-registration.md

159 lines
3.7 KiB
Markdown

# Command Registration
How to register command handlers in dependency injection.
## Basic Registration
### Command with Result
```csharp
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
```
**This registers:**
- Handler as `ICommandHandler<CreateUserCommand, int>`
- Metadata for endpoint discovery
- Scoped lifetime (default)
### Command without Result
```csharp
builder.Services.AddCommand<DeleteUserCommand, DeleteUserCommandHandler>();
```
## Registration with Validator
```csharp
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler, CreateUserCommandValidator>();
```
**This registers:**
- Handler
- Validator as `IValidator<CreateUserCommand>`
- Metadata
## Registration with Workflow
```csharp
builder.Services.AddCommandWithWorkflow<CreateUserCommand, int, UserWorkflow, CreateUserCommandHandler>();
```
For event-emitting commands.
## Service Lifetimes
### Scoped (Default - Recommended)
```csharp
services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
// Handler is Scoped
```
**Characteristics:**
- One instance per request
- Can inject DbContext
- Disposed after request
### Custom Lifetime
```csharp
// Transient
services.AddTransient<ICommandHandler<CreateUserCommand, int>, CreateUserCommandHandler>();
// Singleton (not recommended - can't inject DbContext)
services.AddSingleton<ICommandHandler<CreateUserCommand, int>, CreateUserCommandHandler>();
```
## Bulk Registration
### Extension Methods
```csharp
// 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
```csharp
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](../../architecture/dependency-injection.md) - DI patterns
- [Modular Solution Structure](../../architecture/modular-solution-structure.md)