后端开发
本章节介绍LMES系统后端组件的开发规范、流程和最佳实践。
一、先决条件
- 开发环境: 比如 Visual Studio 2022 或者 Visual Studio Code 它需要支持 .NET 6.0+ 的开 发.
- 已安装 CMS2.0,并且掌握 CMS2.0 平台的操作使用
- 有 c# 开发经验
- 有 mysql、sql server 等数据库开发经验
二、插件模板
1、创建插件解决方案
我们将使用[.NET CLI ](dotnet 命令 - .NET CLI | Microsoft Learn) 来安装基于DDD分层架构的CMS2.0二次开发插件模板. 你可以在命令行终端中运行以下命令来安装它:
dotnet new install CMS.Plugin.Template.Ddd --nuget-source https://nexus.sycdev.com/repository/nuget-group/index.json
如果已经安装该模板,可以使用 dotnet new update 更新已安装 的模板包。

打开命令行终端并在终端中执行以下命令:
dotnet new cms-ddd -n TestPlugin -e Sample

Commands
dotnet new cms-ddd -n MyPluginName -e MyEntityName
Options:
-n: 插件的名称-e: 实体的名称
这将为TestPlugin插件创建一个基于DDD分层架构的解决方案,并添加Sample实体并创建CRUD服务。

调试前请配置好数据库连接字符串:
**{CMSRootPath}**\host\appsettings.Development.json

Code First 迁移:解决方案模版已经配置为使用Entity Framework Core的 Code First 迁移. 如果我们已经更改了数据库映射配置, 我们应该创建一个新的迁移并将更改应用于数据库。

发布插件,插件作为独立运行的模块,也可以独立于项目进行发布。同样我们建议使用脚本发布,打开插件解决方案根目录,修改publish.ps1

发布成功后,将按照插件名称,统一输出到插件解决方案根目录output\publish
2、为现有插件添加新的CRUD服务
我们将使用[.NET CLI ](dotnet 命令 - .NET CLI | Microsoft Learn) 来安装基于DDD分层架构的CMS2.0二次开发实体模板. 你可以在命 令行终端中运行以下命令来安装它:
dotnet new install CMS.Plugin.Template.Ddd.Entity --nuget-source https://nexus.sycdev.com/repository/nuget-group/index.json
如果已经安装该模板,可以使用 dotnet new update 更新已安装的模板包。

打开命令行终端并在终端中执行以下命令:
dotnet new cms-ddd-entity -n TestPlugin -e Order

Commands
dotnet new cms-ddd-entity -n MyPluginName -e MyEntityName
Options:
-n: 插件的名称-e: 实体的名称
这将为TestPlugin插件添加Order实体并创建CRUD服务。

运行后打开Swagger UI,可以看到已经为我们的TestPlugin自动生成了Order文档

3、如果已经安装模版,也可通过VS可视化界面生成插件代码

三、解决方案简介
推荐 将解决方案命名:CMS.Plugin.PluginName,无特殊情况需保持文件目录结构需与解决方案目录结构一致。

1、文档 (doc)
相关的组件文档
2、输出 (output)
编译输出文件夹,默认被忽略,不会上传到git服务器,用于存放编译或发布输出的临时文件。
3、源码 (src)
插件源代码。
4、测试 (test)
单元测试代码。
5、解决方案项 (Solution Items)
一般是放置在项目根目录中的各种配置文件
- **NuGet.config:**在存储库的根目录中添加
nuget.config文件。 这被认为是一种最佳做法,因为它促进了可重复性,并可确保不同的用户具有相同的 NuGet 配置。 可能需要配置clear元素以确保未应用任何用户或计算机特定的配置。 - **README.md:**自述文件是一个组件的入门手册,里面介绍了整个组件的使用、功能等等。所以 README 文件写得好不好,关系到这个组件能不能更容易的被其他人了解和使用。
- **publish.ps1:**发布脚本,用于发布插件,输出到项目根目录的output文件夹,可用于CI、CD自动化工具调用。
- **.gitignore:**Git 忽略文 件:使用该文件来选择性的上传文件。
四、源码分层
由于各插件形态不一,下面讲述的是基于DDD架构的插件分层,仅供参考,具体分层和架构以实际项目插件需要为准。
下面展示了一个分层良好的模块中的包以及它们之间的依赖关系:

1、领域层
-
推荐将领域层划分为两个项目:
-
Domain.Shared 包(项目) 命名为CMS.Plugin.PluginName.Domain.Shared,包含常量,枚举和其他类型, 它不能包含实体,存储库,域服务或任何其他业务对象. 可以安全地与模块中的所有层使用. 此包也可以与第三方客户端使用.
-
Domain 包(项目) 命名为CMS.Plugin.PluginName.Domain 包含实体, 仓储接口,领域服务接口及其实现和其他领域对象.
-
-
Domain 包依赖于 Domain.Shared 包.
2、应用服务层
-
推荐将应用服务层划分为两个项目:
-
Application.Contracts 包(项目) 命名为CMS.Plugin.PluginName.Application.Contracts,包含应用服务接口和相关的数据传输对象(DTO).
- Application contract 包依赖于 Domain.Shared 包.
-
Application 包(项目)命名为CMS.Plugin.PluginName.Application包含应用服务实现.
- Application 包依赖于 Domain 包和 Application.Contracts 包.
-
3、基础设施层
- 推荐为每个orm/数据库集成创建一个独立的集成包, 比如Entity Framework Core 和 MongoDB.
- 推荐 例如, 创建一个抽象Entity Framework Core集成的CMS.Plugin.PluginName.EntityFrameworkCore 包. ORM 集成包依赖于 Domain 包.
- 不推荐 依赖于orm/数据库集成包中的其他层.
- 推荐 为每个主要的库创建一个独立的集成包, 在不影响其他包的情况下可以被另一个库替换.
4、插件启动层
-
推荐 创建命名为CMS.Plugin.PluginName 包. **PluginEntry **为模块开发REST风格的HTTP API.
-
虚线依赖:在上图中会发现用虚线表示了另外两个依赖,PluginEntry项目依赖了 Application 和 EntityFrameworkCore,理论上PluginEntry不应该依赖这两个项目,但实际上依赖了.原因如下:
PluginEntry 是基座加载插件的启动,在启动程序注册服务是需要应用服务和仓储的实现类.
-
推荐 为每个应用服务创 建一个Controller (通常通过实现其接口). 这些控制器使用应用服务接口来委托操作. 它根据需要配置路由, HTTP方法和其他与Web相关的东西.
-
推荐 只在PluginEntry层引入基座提供的包,其他层尽量不依赖基座.
-
五、最佳实践 & 约定
但是EF Core迁移系统在模块化环境中不是很好,在模块化环境中,每个模块都维护自己的数据库模式,而实际上两个或多个模块可以共享一个数据库.
模板已集成ABP 框架 大部分的基础设施,ABP 框架 提供了非常多的开箱即用的功能,开发代码前先阅读Abp文档,不要重复自己一次又一次地实现所有这些常见的东西.专注于你的业务代码,并让ABP按照约定自动执行。
六、插件打包发布
参阅《CMSv2插件打包工具说明.pdf》,使用插件打包工具进行插件打包。