Kiến trúc phổ biến nhất cho enterprise .NET projects. Tách biệt business logic khỏi infrastructure, dễ test, dễ thay đổi technology.
Tổng Quan
Dependency Rule: Mũi tên CHỈ hướng vào trong. Domain KHÔNG biết về Infrastructure.
Khi Nào Dùng / Không Dùng
| ✅ Dùng khi | ❌ Không dùng khi |
|---|---|
| Business logic phức tạp, thay đổi thường xuyên | Simple CRUD app (< 10 entities) |
| Team > 3 devs, cần rõ ràng ownership | Prototype / MVP cần ship nhanh |
| Cần testability cao (unit test domain) | Script, ETL, background jobs đơn giản |
| Dự kiến thay đổi database/infrastructure | Solo dev, side project |
Dự án hay dùng: ERP, eCommerce, Banking, Insurance, Healthcare, Logistics.
Project Structure (.sln)
MyApp/
├── MyApp.sln
│
├── src/
│ ├── MyApp.Domain/ ← Core (0 dependencies)
│ │ ├── Entities/
│ │ │ ├── Order.cs
│ │ │ └── OrderItem.cs
│ │ ├── ValueObjects/
│ │ │ ├── Money.cs
│ │ │ └── Email.cs
│ │ ├── Events/
│ │ │ └── OrderCreatedEvent.cs
│ │ ├── Enums/
│ │ │ └── OrderStatus.cs
│ │ ├── Exceptions/
│ │ │ └── DomainException.cs
│ │ └── Interfaces/
│ │ └── IOrderRepository.cs
│ │
│ ├── MyApp.Application/ ← Use Cases
│ │ ├── Common/
│ │ │ ├── Behaviors/
│ │ │ │ ├── ValidationBehavior.cs
│ │ │ │ └── LoggingBehavior.cs
│ │ │ ├── Interfaces/
│ │ │ │ ├── IUnitOfWork.cs
│ │ │ │ └── ICurrentUser.cs
│ │ │ └── Models/
│ │ │ └── Result.cs
│ │ ├── Orders/
│ │ │ ├── Commands/
│ │ │ │ ├── CreateOrder/
│ │ │ │ │ ├── CreateOrderCommand.cs
│ │ │ │ │ ├── CreateOrderHandler.cs
│ │ │ │ │ └── CreateOrderValidator.cs
│ │ │ ├── Queries/
│ │ │ │ └── GetOrderById/
│ │ │ │ ├── GetOrderByIdQuery.cs
│ │ │ │ └── GetOrderByIdHandler.cs
│ │ │ └── DTOs/
│ │ │ └── OrderDto.cs
│ │ └── DependencyInjection.cs
│ │
│ ├── MyApp.Infrastructure/ ← Implementations
│ │ ├── Persistence/
│ │ │ ├── AppDbContext.cs
│ │ │ ├── Configurations/
│ │ │ │ └── OrderConfiguration.cs
│ │ │ ├── Repositories/
│ │ │ │ └── OrderRepository.cs
│ │ │ ├── Interceptors/
│ │ │ │ └── AuditableEntityInterceptor.cs
│ │ │ └── Migrations/
│ │ ├── Services/
│ │ │ ├── EmailService.cs
│ │ │ └── CacheService.cs
│ │ └── DependencyInjection.cs
│ │
│ └── MyApp.API/ ← Entry Point
│ ├── Controllers/
│ │ └── OrdersController.cs
│ ├── Middleware/
│ │ └── ExceptionHandlerMiddleware.cs
│ ├── Program.cs
│ └── appsettings.json
│
└── tests/
├── MyApp.Domain.Tests/
├── MyApp.Application.Tests/
└── MyApp.API.IntegrationTests/
Project References (Dependency Direction)
NuGet Checklist
xml<!-- MyApp.Domain (KHÔNG có NuGet ngoại trừ MediatR contracts) -->
<PackageReference Include="MediatR.Contracts" Version="2.*" />
<!-- MyApp.Application -->
<PackageReference Include="MediatR" Version="12.*" />
<PackageReference Include="FluentValidation" Version="11.*" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.*" />
<PackageReference Include="AutoMapper" Version="13.*" /> <!-- hoặc Mapster -->
<!-- MyApp.Infrastructure -->
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.*" />
<PackageReference Include="StackExchange.Redis" Version="2.*" />
<!-- MyApp.API -->
<PackageReference Include="Serilog.AspNetCore" Version="8.*" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.*" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.*" />
Code Setup Cốt Lõi
Program.cs (API Layer)
csharpvar builder = WebApplication.CreateBuilder(args);
// Layer registrations
builder.Services
.AddApplication() // MediatR, FluentValidation, Behaviors
.AddInfrastructure(builder.Configuration); // EF Core, Redis, Services
builder.Services.AddControllers();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseExceptionHandler();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Application DI Registration
csharppublic static class DependencyInjection
{
public static IServiceCollection AddApplication(this IServiceCollection services)
{
var assembly = typeof(DependencyInjection).Assembly;
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(assembly));
services.AddValidatorsFromAssembly(assembly);
// Pipeline Behaviors (order matters!)
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
return services;
}
}
Infrastructure DI Registration
csharppublic static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(
this IServiceCollection services, IConfiguration config)
{
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(config.GetConnectionString("Default")));
services.AddScoped<IOrderRepository, OrderRepository>();
services.AddScoped<IUnitOfWork>(sp => sp.GetRequiredService<AppDbContext>());
return services;
}
}