空解决方案是唯一可控起点,因直接建多项目结构易致路径错乱、启动项错位及引用失效;domain层须用.net standard或统一targetframework,禁用基础设施引用,application层仅通过接口依赖infrastructure,配置只由主项目加载。

直接用“新建解决方案”模板建多项目结构,九成会在调试、配置加载、引用解析上出问题——不是代码写错了,是根目录和项目关系从一开始就没对齐。
空解决方案才是唯一可控起点
Visual Studio 里点“新建项目”时勾选“创建解决方案目录”,看似一步到位,实则埋下路径错乱、启动项目错位、类库无法被识别的隐患。尤其是后续要加测试项目、CLI 工具或跨平台类库时,.sln 文件里项目路径会突然变成相对路径错误或硬编码绝对路径。
- 正确做法:打开 VS → 新建项目 → 搜索
Blank Solution(位置在“已安装 → 其他项目类型 → Visual Studio 解决方案”)→ 命名后只生成一个.sln文件 - 再右键解决方案 → 添加 → 新建项目 → 逐个添加主项目(如
WebApi或ConsoleApp)、Domain、Application、Infrastructure等 - 第一个添加的项目默认为启动项目;如需切换,右键目标项目 → 设为启动项目
Domain 层必须是纯 .NET Standard 或统一 TargetFramework
Clean Architecture 要求 Domain 层不依赖任何框架、数据库或 I/O 组件,但它仍得被其他层引用。一旦 Domain 项目用了 net8.0-windows 这类带平台后缀的 Application 层哪怕也是 net8.0,也会因平台不匹配导致编译报错或 using Domain; 不生效。
- 新建
Domain项目时,务必选Class Library (.NET Standard 2.1)(兼容性最强)或Class Library (.NET 6.0)(若全栈都锁定 .NET 6+) - 检查其
.csproj中是否为<targetframework>net6.0</targetframework>,而非net6.0-windows或net8.0-android -
Domain项目中禁止出现Microsoft.Extensions.DependencyInjection、System.Data.SqlClient等任何基础设施相关引用
Application 层不能直接 new Infrastructure 实现类
Clean Architecture 的核心约束是“依赖倒置”:高层模块(Application)不应依赖低层模块(Infrastructure),而应通过接口(定义在 Application 或 Domain 中)与其实现解耦。否则,单元测试时无法 mock 数据访问,且违反了“领域逻辑不可知技术细节”的原则。
-
Application层定义接口,例如IUserRepository,放在Application/Interfaces/下 -
Infrastructure层实现该接口,例如SqlUserRepository,并只在主项目(如WebApi)的Program.cs中注册:services.AddScoped<iuserrepository sqluserrepository>()</iuserrepository> -
Application层代码中只能构造函数注入IUserRepository,绝不可写new SqlUserRepository(...) - 若误在
Application中引用Infrastructure项目,VS 会提示“项目引用循环”或编译失败
appsettings.json 只在主项目加载,Infrastructure 不读配置文件
把连接字符串写进 Infrastructure 项目的 appsettings.json 是无效的——.NET Core / .NET 6+ 只加载启动项目的配置文件。Infrastructure 层若硬编码读取,运行时必抛 NullReferenceException 或 ConfigurationErrorsException。
- 所有配置项(数据库连接串、Redis 地址、第三方 API Key)必须放在主项目(如
WebApi)的appsettings.json中 -
Infrastructure层通过构造函数接收配置值,例如:public SqlUserRepository(string connectionString) - 主项目注册服务时传入:
services.AddScoped<iuserrepository>(sp => new SqlUserRepository(Configuration.GetConnectionString("Default")))</iuserrepository> - 避免在
Infrastructure中使用ConfigurationManager(.NET Framework 风格)或new ConfigurationBuilder()(重复构建配置树,性能差且易错)
最常被跳过的环节是检查每个项目的 TargetFramework 是否真正对齐——不是“看着都是 net6.0”,而是打开每个 .csproj 文件确认标签内容完全一致;另一个隐形陷阱是 Domain 层悄悄引用了 Microsoft.AspNetCore.Http,表面能编译,但一跑单元测试就崩。架构不是图画画得漂亮就行,是每个 .csproj 和每行 using 都得经得起反向依赖检查。











