在上一篇文章《手把手教你用Abp vnext構建API介面服務》中,我們用ABP vnext實作了WebAPI介面服務,但是并非ABP模塊化架構的最佳實踐,我本身也在學習ABP,我認為ABP新手應該從最佳實踐開始學習,可以少走很多彎路,所以寫了這篇最佳實踐來做個總結,同時給其他朋友們提供一點參考,
一、什么是模塊化架構的最佳實踐
ABP是一個包含許多nuget包的模塊化框架,它提供了一個完整的基礎架構來開發你自己的具有物體、服務、資料庫集成、API、 UI組件等等功能的應用程式模塊,
模塊化架構的最佳實踐就是按功能的劃分創建相應的模塊實作的服務,必要時可以把模塊發布到nuget,由其他模塊安裝組合成新的服務或單體應用,這樣就可以復用現有的模塊功能,快速的交付產品,告別996,
二、模塊化架構的最佳實踐說明
這部分內容全部來自于模塊化架構最佳實踐 & 約定,有興趣的朋友可以去官方檔案查看,如果已經很熟悉ABP分層了,可以直接閱讀第三部分,
1、解決方案結構:
- 為每個模塊創建一個單獨的解決方案,將解決方案命名為CompanyName.ModuleName,
- 一個模塊做為分層專案開發,因為它有幾個包(專案)是相互關聯的,每個包都有自己的模塊定義檔案,并顯式宣告所依賴的包/模塊的依賴關系,
2、模塊分層和包之間的關系
下面展示了一個分層良好的模塊中的包以及它們之間的依賴關系:

領域層
將領域層劃分為兩個專案:
- Domain.Shared 包(專案) 命名為CompanyName.ModuleName.Domain.Shared,包含常量,列舉和其他型別,它不能包含物體、存盤庫、域服務或任何其他業務物件,可以安全地與模塊中的所有層使用,此包也可以與第三方客戶端使用,
- Domain 包(專案) 命名為CompanyName.ModuleName.Domain,包含物體、倉儲介面、領域服務介面及其實作和其他領域物件,Domain 包依賴于 Domain.Shared 包,
應用服務層
將應用服務層劃分為兩個專案:
- Application.Contracts 包(專案) 命名為CompanyName.ModuleName.Application.Contracts,包含應用服務介面和相關的資料傳輸物件(DTO), Application contract 包依賴于 Domain.Shared 包,
- Application 包(專案)命名為CompanyName.ModuleName.Application,包含應用服務實作,Application 包依賴于 Domain 包和 Application.Contracts 包,
基礎設施層
- 為每個orm/資料庫集成創建一個獨立的集成包,比如Entity Framework Core 和 MongoDB,例如,創建一個抽象Entity Framework Core集成的CompanyName.ModuleName.EntityFrameworkCore 包,ORM 集成包依賴于 Domain 包,不推薦依賴于orm/資料庫集成包中的其他層.
- 為每個主要的庫創建一個獨立的集成包, 在不影響其他包的情況下可以被另一個庫替換.
HTTP 層
- 創建命名為CompanyName.ModuleName.HttpApi的HTTP API包,為模塊開發REST風格的HTTP API,
- HTTP API 包只依賴于 Application.Contracts 包,不要依賴 Application 包,
- 為每個應用服務創建一個Controller (通常通過實作其介面),這些控制器使用應用服務介面來委托操作,它根據需要配置路由,HTTP方法和其他與Web相關的東西,
- 創建一個為HTTP API包提供客戶端服務的HTTP API Client包,它的命名為Companyname.ModuleName.HttpApi.Client,這些客戶端服務將應用服務介面實作遠程端點的客戶端,
- HTTP API Client包僅依賴于 Application.Contracts包,
- 推薦使用ABP框架提供的動態代理HTTP C#客戶端的功能,
Web 層
創建命名為CompanyName.ModuleName.Web的Web包, 包含頁面、視圖、腳本、樣式、影像和其他UI組件,Web包僅依賴于HttpApi包,
三、實作模塊化架構的最佳實踐
開發環境:Mac Visual Studio Code
SDK:dotnet core 3.1
資料庫:PostgreSQL
創建專案檔案夾,然后進入改檔案夾的命令目錄執行以下命令創建專案
在上一篇文章中引入的是Volo.Abp.Identity的包,現在改用Volo.Abp.DDD的包,更簡潔,
/**創建解決方案**/
dotnet new sln
/**創建模塊分層**/
dotnet new classlib -o src/Lemon.Account.Domain.Shared
dotnet new classlib -o src/Lemon.Account.Domain
dotnet new classlib -o src/Lemon.Account.EntityFrameworkCore
dotnet new classlib -o src/Lemon.Account.EntityFrameworkCore.DbMigrations
dotnet new classlib -o src/Lemon.Account.Application.Contracts
dotnet new classlib -o src/Lemon.Account.Application
dotnet new classlib -o src/Lemon.Account.HttpApi
dotnet new classlib -o src/Lemon.Account.HttpApi.Client
dotnet new web -o src/Lemon.Account.Host
/**加入解決方案**/
dotnet sln Lemon.Account.sln add src/Lemon.Account.Domain.Shared
dotnet sln Lemon.Account.sln add src/Lemon.Account.Domain
dotnet sln Lemon.Account.sln add src/Lemon.Account.EntityFrameworkCore
dotnet sln Lemon.Account.sln add src/Lemon.Account.EntityFrameworkCore.DbMigrations
dotnet sln Lemon.Account.sln add src/Lemon.Account.Application.Contracts
dotnet sln Lemon.Account.sln add src/Lemon.Account.Application
dotnet sln Lemon.Account.sln add src/Lemon.Account.HttpApi
dotnet sln Lemon.Account.sln add src/Lemon.Account.HttpApi.Client
dotnet sln Lemon.Account.sln add src/Lemon.Account.Host
/**分層間互相參考**/
dotnet add src/Lemon.Account.Domain/Lemon.Account.Domain.csproj reference src/Lemon.Account.Domain.Shared/Lemon.Account.Domain.Shared.csproj
dotnet add src/Lemon.Account.EntityFrameworkCore/Lemon.Account.EntityFrameworkCore.csproj reference src/Lemon.Account.Domain/Lemon.Account.Domain.csproj
dotnet add src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj reference src/Lemon.Account.EntityFrameworkCore/Lemon.Account.EntityFrameworkCore.csproj
dotnet add src/Lemon.Account.Application/Lemon.Account.Application.csproj reference src/Lemon.Account.Application.Contracts/Lemon.Account.Application.Contracts.csproj
dotnet add src/Lemon.Account.Application/Lemon.Account.Application.csproj reference src/Lemon.Account.Domain/Lemon.Account.Domain.csproj
dotnet add src/Lemon.Account.HttpApi/Lemon.Account.HttpApi.csproj reference src/Lemon.Account.Application.Contracts/Lemon.Account.Application.Contracts.csproj
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj reference src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj reference src/Lemon.Account.Application/Lemon.Account.Application.csproj
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj reference src/Lemon.Account.HttpApi/Lemon.Account.HttpApi.csproj
/**添加nuget依賴包**/
dotnet add src/Lemon.Account.Domain.Shared/Lemon.Account.Domain.Shared.csproj package Volo.Abp.Validation
dotnet add src/Lemon.Account.Domain/Lemon.Account.Domain.csproj package Volo.Abp.Ddd.Domain
dotnet add src/Lemon.Account.Domain/Lemon.Account.Domain.csproj package Lemon.Common
dotnet add src/Lemon.Account.EntityFrameworkCore/Lemon.Account.EntityFrameworkCore.csproj package Volo.Abp.EntityFrameworkCore
dotnet add src/Lemon.Account.EntityFrameworkCore/Lemon.Account.EntityFrameworkCore.csproj package Volo.Abp.EntityFrameworkCore.PostgreSql
dotnet add src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj package Volo.Abp.EntityFrameworkCore
dotnet add src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj package Volo.Abp.EntityFrameworkCore.PostgreSql
dotnet add src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj package Microsoft.EntityFrameworkCore.Design
dotnet add src/Lemon.Account.Application.Contracts/Lemon.Account.Application.Contracts.csproj package IdentityModel
dotnet add src/Lemon.Account.Application.Contracts/Lemon.Account.Application.Contracts.csproj package Volo.Abp.Ddd.Application.Contracts
dotnet add src/Lemon.Account.Application/Lemon.Account.Application.csproj package Volo.Abp.Ddd.Application
dotnet add src/Lemon.Account.Application/Lemon.Account.Application.csproj package Volo.Abp.AutoMapper
dotnet add src/Lemon.Account.HttpApi/Lemon.Account.HttpApi.csproj package Volo.Abp.AspNetCore.Mvc
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Volo.Abp.AspNetCore.Mvc
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Swashbuckle.AspNetCore
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Microsoft.AspNetCore.DataProtection.StackExchangeRedis
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Microsoft.Extensions.Caching.StackExchangeRedis
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Serilog.AspNetCore
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Serilog.Settings.Configuration
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Serilog.Sinks.Async
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Serilog.Sinks.File
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Volo.Abp.AspNetCore.Serilog
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package Volo.Abp.Autofac
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj package IdentityServer4.AccessTokenValidation
dotnet add src/Lemon.Account.Host/Lemon.Account.Host.csproj reference src/Lemon.Account.EntityFrameworkCore.DbMigrations/Lemon.Account.EntityFrameworkCore.DbMigrations.csproj
實作領域層
在Domain創建物體類及其約束關聯,具體代碼請看UserData類,此處不再詳細說明,
實作基礎設施層
在EntityFrameworkCore創建AccountDbContext類和LemonAccountDbContextModelCreatingExtensions類,請特別關注LemonAccountDbContextModelCreatingExtensions類,主要是用來定義物體在資料庫表中的欄位屬性,
實作應用服務層
實作httpapi
用swagger除錯介面
進入Host目錄,執行命令
dotnet watch run

服務啟動成功,在瀏覽器打開鏈接http://localhost:5000/swagger/index.html,開始除錯賬號注冊和驗證介面,結果如下:




四、模塊化架構的最佳實踐的好處
使用模塊化架構的好處有幾點:
- 可以方便的更換模塊
比如我現在用的資料庫是PostgreSQL,如果想要更換成MySQL,只要以EntityFrameworkCore層為基礎,新增一個MySQL連接庫,就可以在不改變業務邏輯的前提下快速的切換資料庫,
dotnet new classlib -o src/Lemon.Account.EntityFrameworkCore.MySQL
dotnet new classlib -o src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations
dotnet sln Lemon.Account.sln add src/Lemon.Account.EntityFrameworkCore.MySQL
dotnet sln Lemon.Account.sln add src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations
dotnet add src/Lemon.Account.EntityFrameworkCore.MySQL/Lemon.Account.EntityFrameworkCore.MySQL.csproj reference src/Lemon.Account.Domain/Lemon.Account.Domain.csproj
dotnet add src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations.csproj reference src/Lemon.Account.EntityFrameworkCore.MySQL/Lemon.Account.EntityFrameworkCore.MySQL.csproj
dotnet add src/Lemon.Account.EntityFrameworkCore.MySQL/Lemon.Account.EntityFrameworkCore.MySQL.csproj package Volo.Abp.EntityFrameworkCore.MySQL
dotnet add src/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations/Lemon.Account.EntityFrameworkCore.MySQL.DbMigrations.csproj package Microsoft.EntityFrameworkCore.Design
最后再修改ConnectionStrings default為mysql的連接,修改LemonAccountHostModule的依賴項LemonAccountEntityFrameworkCoreDbMigrationsModule為MySQL
-
單體應用和微服務無縫切換
模塊開發完成后,一般當作微服務來部署;或者把模塊發布到nuget,在單體應用的各個分層中引入模塊,多個模塊在單體應用中的應用就構成了一個完整系統服務, -
模塊復用
由于模塊是發布到nuget的,所以如果有新的專案需要用到相同功能的,可以直接從nuget引入安裝,無需重復開發或者復制代碼, -
自動API控制器
-
動態 C# API 客戶端
GiHub地址:https://github.com/huangbenq/abp-samples
參考檔案:
- 模塊化:https://docs.abp.io/zh-Hans/abp/latest/Module-Development-Basics
- 最佳實踐:https://docs.abp.io/zh-Hans/abp/latest/Best-Practices/Index
- 自動API控制器:https://docs.abp.io/zh-Hans/abp/latest/API/Auto-API-Controllers
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/172072.html
標籤:.NET Core
上一篇:[C#] 屬性的事情
