这是一个 Web API 的 Clean Architecture 的解决方案模板,可用于学习和中小型项目。
该项目使用了以下技术和库:
- ASP.NET Core 6
- Entity Framework Core 6 - postgres
- Microsoft ASP.NET Core Identity with JWT
- MediatR
- AutoMapper
- FluentValidation
- XUnit, FluentAssertions, NSubstitute, SpecFlow & TestContainers
- Docker & Docker Compose
相信该项目中用到的一些技术和库会是您感兴趣的。
如果您喜欢这个项目,正在使用这个项目来学习,或使用这个模板构建您自己的项目,请给它一个 Star,谢谢!
我个人并不喜欢使用模板,少了一些禅意,多了一些功利,常常使项目引入了不需要的库,把项目膨胀的越来越大。dotnet sdk 自带的模板足够用,构建本项目是为了学习。所以我并不建议您使用该模板构建自己的项目。
每个人对 Clean Architecture 的期待都不同,如果您觉得该项目有可取之处,也有不满意的地方,强烈建议您 fork 这个项目来构建您自己的 Clean Architecture 模板。也可直接使用该项目生成您自己的解决方案,然后进行自定义的调整,作为您自己的 Clean Architecture 模板。
如果您喜欢我的代码,欢迎关注我的微信公众号:
以及我的博客:https://blog.kitlau.dev/
该模板尚未上传到 Nuget,如果您想安装该模板到 dotnet new 的菜单中,可以按如下步骤操作:
- 确定您的设备已经安装 dotnet 6 SDK
- clone 该仓库,在解决方案的根目录下运行
dotnet new --install .\
命令,即可安装该模板:PS C:\Users\kit\Documents\GitHub\CleanArchitecture> dotnet new --install .\ The following template packages will be installed: C:\Users\kit\Documents\GitHub\CleanArchitecture Success: C:\Users\kit\Documents\GitHub\CleanArchitecture installed the following templates: Template Name Short Name Language Tags ------------------------------- ---------- -------- ------------------------------ Kit Clean Architecture Solution kit-ca-sln [C#] Web/ASP.NET/Clean Architecture
- 为您的解决方案创建一个文件夹,并 cd 到该文件夹下,模板将使用该文件夹名作为项目名称
- 运行
dotnet new kit-ca-sln
即可创建基于该模板的项目 - 继续浏览该文档,选择一种方式运行该项目
需要以下环境:
在解决方案根目录中运行 dotnet run --project .\src\WebAPI\
即可。默认使用 InMemoryDatabase 内存数据库。
在 Development 环境下,会生成基于 swagger-ui 的 API 文档,访问 https://localhost:7279/swagger/index.html
查看该文档。
如果想使用实例数据库,可以继续往下看。
也可以选择完全使用 docker compose 运行该项目,程序与数据库均运行于 docker 容器中:
- 根据您自己的需求,调整 src/WepAPI 目录中 Dockerfile 和 .dockerignore 的各项配置
- 根据您自己的需求,调整解决方案根目录中 docker-compose.yml 中的各项配置
- 在解决方案根目录中运行命令
docker compose up
即可 如果您自定义配置后,环境变量 ASPNETCORE_ENVIRONMENT 依然为 Development,则依旧会生成 API 文档。
首先需要有一个 Postgres 数据库实例,没有也没关系,可以用 Docker 方便地创建:
- 如果运行在 Windows 系统,建议 Docker 使用基于 WSL2 的引擎(Use the WSL 2 based engine),因为该项目默认的 DockerDefaultTargetOS 是 Linux,不确定不使用 WSL2 会出什么奇怪问题
- 方案 1:运行以下命令,run 一个 Postgres 的容器。请将 -e 的各项环境变量值替换为您自己的值:
docker run --name postgres_default -e POSTGRES_USER=kitlau -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres:latest
- 方案 2:在解决方案根目录中运行以下命令:
会启动 docker-compose.yml 中配置的 Postgres 容器,默认 Port: 10002,Username: kitlau, Password: password。您也可以手动编辑 docker-compose.yml 进行配置
docker compose up -d clean_architecture.database
- 修改 src/WebAPI/ 目录中的 appsettings.json 的配置:
"UseInMemoryDatabase": false, // true 改为 false,表示不启用内存数据库 "ConnectionStrings": { "DefaultConnection": "Host=localhost;Port=5432;Username=kitlau;Password=password;Database=CleanArchitecture" // 按照您使用的数据库参数修改连接字符串 },
在解决方案根目录中运行 dotnet run --project .\src\WebAPI\
即可。此时已经使用实例数据库。
如果您使用该项目为模板,进行了需要添加新 Migration 的改动,可以在解决方案根目录下运行以下命令添加 Migration:
dotnet ef migrations add "SampleMigration" --project src\Infrastructure --startup-project src\WebUI --output-dir Persistence\Migrations
该项目非常适合入门单元测试,集成测试和接收测试。在 tests 目录中的各个测试项目使用了以下常用技术:
- XUnit - 测试框架
- FluentAssertions - 非常方便的 Assert 库
- NSubstitute - 用于代替 Moq 的库,我个人认为比 Moq 更易于使用
- SpecFlow - 常用于集成测试和接收测试
测试项目还有一些特色:
tests/Application.Tests.Integration 项目使用 postgres docker 容器作为测试数据库,每个测试类/方法使用单独的数据库容器,使各测试类/方法之间互不影响,可以尽情对数据进行任何操作。
各容器会在运行测试时自动创建,使用完毕后自动停止,自动删除,干净利落。
tests/接收测试的环境和数据库会通过 docker compose 创建,您不需要手动运行 WebAPI,只运行测试即可。
未来计划:
- 替换掉常规业务逻辑中抛异常的报错模式,改为直接返回 Error - 这种方式正日趋流行
- 修改 EF Core 配置的方式 - 目前的配置方式略显笨拙
- 修改授权认证代码 - 目前在认证出错时返回值很乱
本解决方案将不会:
- 引入 Serilog 或 NLog 等日志库 - 引入日志库并非难事,而且每个人的选择可能不同,引入我自己喜欢的库反而使这个解决方案模板不够 clean
该项目使用 jasontaylordev/CleanArchitecture 模板构建,虽重写了部分代码,但总体的 Architecture 依然相似。
目前有很多优秀的 Clean Architecture 模板,例如 ardalis/CleanArchitecture。其中我最喜欢 jason taylor 的架构和分层方式,所以选择了他的模板。
我起初只是想使用模板构建项目,节省时间。后来我发现它依赖了 Microsoft.AspNetCore.ApiAuthorization.IdentityServer 这个库,该库又依赖了 Duende.IdentityServer,一个付费的库。 很多像我一样的贫困开发者承担这些付费库很困难。
而且 jason taylor 的模板直接在 WebUI 层加了一个 Angular 的 SPA 模板,swagger 的生成方式也很奇怪,调用了本地的 C 盘里的一个 dll,看起来像使用 dotnet sdk 自带的 Angular 模板生成的。可能因为我本地环境有点乱,我运行的前 4 次就失败了两次,无法直接运让我难以接受。
后来我又看了各个流行的 Clean Architecture 模板,但是它们都有各种不合我胃口的地方,例如 ardalis 的模板使用了 Autofac,它很好,只是我觉得引入了它不符合我对 clean 的期待了。
这几个项目都有各自合与不合我胃口的点,所以对我来说:
所以就有了该项目。该项目本身是 clean 的,仅仅在测试时比较依赖 docker。这也是这个项目的 clean 点之一,您不需要自己进行除 dotnet sdk 和 Docker 之外的配置,docker 会帮您完成一切。
如果您不喜欢 docker,可以轻松地改写或删除对 TodoList 和 TodoItem 功能的这些依赖 docker 的测试,毕竟您的项目大概率用不到这些功能。
在我看来,写这个项目的学习意义大于实用意义。只有少量功能的项目不需要 Clean Architecture,用它只会多写很多 Query/Command 和 Handler,徒增代码的复杂程度,反而直接三层,一层,甚至 MinimalAPI 就能实现需求;写大型项目,社区又有为大型项目准备的框架。
但是在写该项目时让我思考了很多问题,通过解决这些问题,又学到很多。