.NET Core 9 DDD Architecture
Enforce Domain-Driven Design (DDD) and SOLID principles for .NET Core 9 applications using modern C# patterns, minimal APIs, and architectural best practices.
What This Skill Does
This skill guides AI assistants to generate C# code following:
Domain-Driven Design (DDD) architectural patternsSOLID principles throughout the applicationModern C# features (primary constructors, file-scoped namespaces)Clean architecture with clear layer separationProper validation, logging, caching, and data mappingInstructions for AI Agent
When writing C# code for this project, follow these rules strictly:
1. Primary Constructors
**Always use primary constructors** in C# when possiblePrefer primary constructor syntax over traditional constructorsApply especially in domain classes and entities**Example:**
```csharp
public class User(string name, string email)
{
public string Name { get; } = name;
public string Email { get; } = email;
}
```
2. File-Scoped Namespaces
**Always use file-scoped namespace declarations**Use the syntax: `namespace Domain.AggregatesModel.UserAggregate;` (no braces)**Example:**
```csharp
namespace Domain.AggregatesModel.UserAggregate;
public class User(string name, string email)
{
// class implementation
}
```
3. Architectural Patterns
**SOLID principles**: Apply Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion**DDD**: Use Aggregates, Entities, Value Objects, Domain Services, Repositories**MediatR**: Use for communication between layers (Commands, Queries, Handlers)**FluentValidation**: Use for all data validation (never manual validation)**AutoMapper**: Use for converting between DTOs and domain models4. API Endpoints
**Always use minimal API** for endpoints (never controllers)Define endpoints in separate endpoint classes or extension methods**Example:**
```csharp
public static class UserEndpoints
{
public static void MapUserEndpoints(this IEndpointRouteBuilder app)
{
app.MapGet("/users/{id}", async (int id, IMediator mediator) =>
{
var result = await mediator.Send(new GetUserQuery(id));
return Results.Ok(result);
});
}
}
```
5. Validation
**Use FluentValidation** for all validationsCreate validator classes inheriting from `AbstractValidator<T>`Register validators in dependency injection**Example:**
```csharp
namespace Application.Validators;
public class CreateUserCommandValidator : AbstractValidator<CreateUserCommand>
{
public CreateUserCommandValidator()
{
RuleFor(x => x.Email).NotEmpty().EmailAddress();
RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
}
}
```
6. Entity Framework Core
**Never create migrations manually**Let EF Core generate migrations automaticallyUse `dotnet ef migrations add` command for new migrations7. Infrastructure
**Serilog**: Use for structured logging**Microsoft.Extensions.Caching.Memory**: Use for in-memory caching**Microsoft.Extensions.Logging**: Use for logging abstractions8. Documentation
**Use Markdown** for all documentationAdd documentation files to the `docs/` folderUse proper Markdown syntax for headings, lists, code blocks9. General Best Practices
Follow C# naming conventionsUse async/await for all I/O operationsApply dependency injection throughoutKeep domain logic pure and free of infrastructure concernsSeparate concerns across layers (Domain, Application, Infrastructure, API)Example Usage
When asked to "create a user registration endpoint":
1. Create a `CreateUserCommand` in Application layer
2. Create a `CreateUserCommandValidator` using FluentValidation
3. Create a `CreateUserCommandHandler` using MediatR
4. Create a minimal API endpoint that sends the command
5. Use primary constructors and file-scoped namespaces
6. Document the endpoint in Markdown
Constraints
Never use traditional constructors when primary constructors are possibleNever create manual validations (always FluentValidation)Never use controller-based APIs (always minimal APIs)Never create EF Core migrations manuallyNever use block-scoped namespaces (always file-scoped)