关于 dotnet-core
.NET 8 后端服务的架构规范技能,面向设计和维护服务的开发者。内容涵盖分层、领域模型、验证、可观测性与测试,并说明何时采用 CQRS 和 AOT。
主要功能
- 01依赖向内的分层架构
- 02实体工厂与不变量约束
- 03CQRS 与管道行为规范
- 04Minimal APIs 按功能分组
- 05健康检查与结构化日志
- 06集成测试与容器建议
适用场景
- 01规划 .NET 8 服务的项目结构
- 02审查领域层与基础设施边界
- 03统一验证和横切关注点处理
- 04设计服务健康检查与集成测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ alexander-danilenko/ cortex-ai-skills --skill dotnet-core安装后在 Claude Code 中输入/dotnet-core确认已加载。
详细介绍
.NET Core 架构
.NET 8 后端服务的架构约定。本文介绍服务的_结构_;语言层面的约定请参阅 csharp 技能。
分层
依赖只能指向内层。领域层对其他所有内容一无所知,而基础设施层是唯一允许引用数据库或 SDK 的层——因此内层无需依赖这两者也能进行测试。
Domain entities, value objects, domain events, interfaces → no dependencies
Application use cases, CQRS handlers, DTOs, validators → Domain
Infrastructure EF Core, external APIs, implementations of Domain interfaces → Domain + Application
Api endpoints, DI wiring, middleware → all of the above
确保这一约定得到遵守的测试是:如果 Domain 除了 BCL 之外不依赖任何包就能编译,那么边界就是完整的。
实体负责维护自身的不变条件:使用私有 setter、为 EF Core 的物化器提供私有无参构造函数,以及负责验证的静态工厂。公开 setter 意味着任何层都能将实体置于无效状态;此时“领域保证 X”就只是一句注释。
public class Product
{
public string Name { get; private set; } = string.Empty;
public decimal Price { get; private set; }
private Product() { } // EF Core materialisation only
public static Product Create(string name, decimal price) =>
price <= 0
? throw new DomainException("Price must be greater than zero")
: new Product { Name = name, Price = price };
}
约定
- 仅当读写确实存在差异时,才使用 MediatR 实现 CQRS——例如模型、数据一致性或扩展方式不同。对 CRUD 服务而言,这只是形式主义;应根据领域需求采用,而不是默认使用。
- 横切关注点应放在管道行为中,而不是处理程序中。将验证、日志记录和事务一次性写入行为后,就能应用于每个处理程序,也不会在新增处理程序时遗漏。
- 使用
MapGroup对 Minimal API 进行分组,每个功能领域使用一个文件。Program.cs集中放置所有端点时,路由数量达到约 20 个就会变得难以阅读。 - 在 Application 边界进行验证(在行为中使用 FluentValidation),这样无论通过哪个入口点调用用例,都适用相同规则。只在端点进行验证,只能保护 HTTP 入口。
- DbContext 应留在 Infrastructure 中,由 Application 层拥有的接口提供访问。将
DbContext泄漏到处理程序中,会使你的用例绑定到 EF,并且无法在没有提供程序的情况下进行测试。 - 绝不将密钥放入
appsettings.json——本地使用 user-secrets,生产环境使用环境变量或密钥库。任何已提交的密钥都已泄露;轮换密钥还意味着需要重新部署。 - 从一开始就设置运行状况检查(
/health/live、/health/ready)和带关联 ID 的结构化日志。在故障正在发生时才补充可观测性,不是发现自己毫无监控的好时机。务必让两个探针真正有所区别:就绪探针可以检查数据库和下游 API;存活探针只能检查进程本身是否存活。若存活探针 ping 数据库,数据库短暂抖动时就会重启每个 Pod,将可恢复的依赖故障变成全面中断。 - 容器应以非 root 用户运行。 添加一行
USER——默认以 root 身份运行的容器会将进程级入侵扩大到主机级权限,而只需一行配置就能避免这种情况。 - 使用
WebApplicationFactory编写集成测试,并连接真实数据库(Testcontainers)。这类测试会覆盖 DI 依赖图、路由、序列化和 EF 映射——这些正是被模拟的单元测试会在服务已损坏时仍报告成功的层。 - 只有在启动时间或占用空间确实有要求时才使用 AOT。 AOT 不支持运行时反射,这可能会悄无声息地破坏某些序列化器和 DI 模式;在决定采用之前,先验证整个技术栈都能兼容。
评论
支持 Markdown