使用模板进行后端开发
介绍使用模板进行后端开发
一、快速入门
1、先决条件
- 一个集成开发环境 (比如: Visual Studio) 它需要支持 .NET 6.0+ 的开发.
- 安装 CMS2.0基座运行调试需要使用到,以下示例开发版安装路径示例{CMSRootPath}:C:\WorkSpace\CMS\CMS Editor
2、创建项目解决方案
我们将使用.NET CLI 来安装CMS2.0二次开发项目模板. 你可以在命令行终端中运行以下命令来安装它:
dotnet new install CMS.Project.Template --nuget-source https://nexus.sycdev.com/repository/nuget-group/index.json
如果已经安装该模板,可以使用 dotnet new update 更新已安装的模板包。
打开命令行终端并在终端中执行以下命令:
dotnet new cms-project -n Demo -p Sample
Commands
dotnet new cms-project -n MyProjectName -p MyPluginName
Options:
-n
: 项目的名称-p
: 插件的名称
这将为Demo项目创建一个新解决方案,并添加一个Sample插件。
注意:调试前需先开启redis-server.exe、IOServiceCxx.exe
- {CMSRootPath}\ref-bin\redis\redis-server.exe
- {CMSRootPath}\ref-bin\siot\IOServiceCxx.exe
设置CMS.Plugin.Sample为启动项目,然后运行应用程序(Visual Studio中是Ctrl+F5)来查看初始UI:
发布项目,由于一个项目中可能包含多个插件,我们建议使用脚本批量发布,打开项目解决方案根目录,修改publish.ps1 并执行。
发布成功后,插件将按照插件名称,统一输出到项目解决方案根目录output\publish
3、创建插件解决方案
我们将使用[.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
4、为现有插件添加新的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文档
二、项目解决方案简介
推荐 将项目解决方案命名:CMS.Project.ProjectName,无特殊情况需保持文件目录结构需与解决方案目录结构一致。
2.1、文档 (doc)
与研发相关的项目文档。
2.2、输出 (output)
项目编译输出文件夹,默认被忽略,不会上传到git服务器,用于存放编译或发布输出的临时文件,建议输出的子目录按插件名称定义。
2.3、插件 (plugins)
推荐 在Visual Sudio中为每个插件创建一个单独的解决方案.
推荐 将插件解决方案命名为CMS.Plugin.PluginName.
推荐 一个插件做为分层项目开发,因为它有几个包(项目)是相互关联的,每个包都有自己的模块定义文件,并显式声明所依赖的包/模块的依赖关系.
2.4、共享代码 (shared)
同一个项目中,插件间可能需要共享代码,接口契约,为了保证各插件间解耦,相互不受影响, 将共享代码放到CMS.Project.ProjectName.Shared类库中。
此处为了避免DLL冲突,共享层命名需带上 ProjectName。
2.5、解决方案项 (Solution Items)
一般是放置在项目根目录中的各种配置文件
- NuGet.config:在项目存储库的根目录中添加
nuget.config
文件。 这被认为是一种最佳做法,因为它促进了可重复性,并可确保不同的用户具有相同的 NuGet 配置。 可能需要配置clear
元素以确保未应用任何用户或计算机特定的配置。 - README.md:自述文件是一个项目的入门手册,里面介绍了整个项目的使用、功能等等。所以 README 文件写得好不好,关系到这个项目能不能更容易的被其他人了解和使用。
- publish.ps1:发布脚本,用于发布整个项目的所有插件,输出到项目根目录的output文件夹,可用于CI、CD自动化工具调用。
- .gitignore:Git 忽略文件:使用该文件来选择性的上传文件。
三、插件分层(layers) & 包(packages)
由于各插件形态不一,下面讲述的是基于DDD架构的插件分层,仅供参考,具体分层和架构以实际项目插件需要为准。
下面展示了一个分层良好的模块中的包以及它们之间的依赖关系:
3.1、领域层
推荐将领域层划分为两个项目:
Domain.Shared 包(项目) 命名为CMS.Plugin.ModuleName.Domain.Shared,包含常量,枚举和其他类型, 它不能包含实体,存储库,域服务或任何其他业务对象. 可以安全地与模块中的所有层使用. 此包也可以与第三方客户端使用.
Domain 包(项目) 命名为CMS.Plugin.ModuleName.Domain 包含实体, 仓储接口,领域服务接口及其实现和其他领域对象.
Domain 包依赖于 Domain.Shared 包.
3.2、应用服务层
推荐将应用服务层划分为两个项目:
Application.Contracts 包(项目) 命名为CMS.Plugin.ModuleName.Application.Contracts,包含应用服务接口和相关的数据传输对象(DTO).
- Application contract 包依赖于 Domain.Shared 包.
Application 包(项目)命名为CMS.Plugin.ModuleName.Application包含应用服务实现.
- Application 包依赖于 Domain 包和 Application.Contracts 包.
3.3、基础设施层
- 推荐为每个orm/数据库集成创建一个独立的集成包, 比如Entity Framework Core 和 MongoDB.
- 推荐 例如, 创建一个抽象Entity Framework Core集成的CMS.Plugin.ModuleName.EntityFrameworkCore 包. ORM 集成包依赖于 Domain 包.
- 不推荐 依赖于orm/数据库集成包中的其他层.
- 推荐 为每个主要的库创建一个独立的集成包, 在不影响其他包的情况下可以被另一个库替换.
3.4、插件入口层
推荐 创建命名为CMS.Plugin.ModuleName 包. PluginEntry 为模块开发REST风格的HTTP API.
虚线依赖:在上图中会发现用虚线表示了另外两个依赖,PluginEntry项目依赖了 Application 和 EntityFrameworkCore,理论上PluginEntry不应该依赖这两个项目,但实际上依赖了.原因如下:
PluginEntry 是基座加载插件的入口,在启动程序注册服务是需要应用服务和仓储的实现类.
推荐 为每个应用服务创建一个Controller (通常通过实现其接口). 这些控制器使用应用服务接口来委托操作. 它根据需要配置路由, HTTP方法和其他与Web相关的东西.
推荐 只在PluginEntry层引入基座提供的包,其他层尽量不依赖基座.
四、共享模块插件
CMS 2.0 共享模块插件 · GitLab (syc-cms.com),欢迎大家参与贡献代码。
1、框架模块: 框架的核心模块,像缓存,邮件,主题,安全性,序列化,验证,Ef Core集成,MongoDB集成...等等.
2、应用程序模块: 像配方管理, 订单管理, 设置户管理... 等等. 它是通常有自己的实体,服务,API组件.
- Setting Management [已完成]:设置管理,设置存储在动态数据源(通常是数据库)中的键值对. 设置系统预构建了用户,全局和默认设置方法并且可以进行扩展.
- Audit Logging:审计日志:审计跟踪(也称为审计日志)是一种安全相关的按时间顺序记录,记录集或记录目的和来源. 这种记录提供了在任何特定时间的操作,过程或事件产生影响活动顺序的文件证据
- Background Jobs:后台作业用来在后台里执行应用里的一些任务, 出于几个原因, 你可能需要后台工作: 1:为执行长时间运行的任务而用户无需等待. 2:创建可重试和持久的任务以确保代码将成功执行.
- Virtual File Explorer:虚拟文件系统使得管理物理上不存在于文件系统中(磁盘)的文件成为可能. 它主要用于将(js, css, image...)文件嵌入到程序集中, 并在运行时将它们像物理文件一样使用.