# Xncf 的构成
# 前言
此文档介绍 Xncf 模块代码的重要组成部分,有助于开发者了解其原理,开发 Xncf 不需要手敲这些代码,可以使用 Xncf模块生成器 可视化配置并生成。
# 什么是 Xncf?
Xncf(XNCF)是组成 NCF 系统功能的各个独立模块的称呼,通常以单一的项目出现(如类库,使用 .csproj 引入解决方案),特殊情况下也可以由多个项目组成。为了能够在发布包中包含 Xncf 模块的 dll,Xncf 需要被 Web 项目(Senparc.Web)直接或间接引用。
Xncf 可以作为 DDD 开发模式中的一个完整 Domain 的项目进行规划,其中包含了所有 DDD 需要的标准结构。
XNCF 项目的文件构成可以理解为一个普通的类库,加上一个特殊的 Register 类 构成。
因此,您几乎可以将任何的类库,通过添加一个
Register
类即可变为一个即插即用的 XNCF 模块!
# Xncf 的命名规则
Xncf 项目的命名(通常也是 dll 的文件名),每一个 Xncf 模块都需要具备一个全局唯一的模块名称,需要符合以下格式:
<组织名字>
.Xncf.<模块名称>
<组织名字>
通常为公司或团队的名字,用于区分不同组织提供的模块,防止<模块名称>
冲突.Xncf.
固定字符,表明这是一个 Xncf 模块,同时用于分割组织名字和模块名称<模块名称>
是当前模块的名称,此名称中不能再出现.
,如还存在下级模块可以试用下划线_
最终 Xncf 命名如:Senparc.Xncf.DatabaseTool
或 Senparc.Xncf.DatabaseTool_Backup
。
# Xncf 模块的几个重要概念
对象 | 说明 |
---|---|
Register 类 | |
[XncfRegister] 特性 | |
IxncfRegister 接口 | |
更多可选接口 |
# IXncfRegister 接口(必须)
必须要包含的接口是:IXncfRegister
(所属基础库:Senparc.Ncf.XncfBase)。
IXncfRegister
接口中包含了模块名称、全局唯一编号、版本号、菜单名称、图标等模块元数据信息,并且可以定义模块安装、卸载等过程中需要执行的代码。
关于 IXncfRegister
接口的详细介绍请见:IXncfRegister。
为了方便开发者使用,NCF 默认提供了一个基于 IXncfRegister
接口的实现:XncfRegisterBase
,因此,通常我们只需要在项目中,创建一个 Register.cs
类文件,然后继承 XncfRegisterBase
基类,并实现其指定的接口,即可使这个项目快速变成一个 Xncf 模块。
# [XncfRegister] 特性
在每个模块项目自定义的 Register
类上,使用 [XncfRegister] 特性,使系统可以快速识别当前类为 Xncf 注册类(预留功能,建议都加上)。
根据上述的要求,一个最小化的 Xncf 模块注册类,可能如下所示:
using Senparc.Ncf.XncfBase;
using System;
using System.Collections.Generic;
namespace Senparc.Xncf.XncfBuilder
{
[XncfRegister]
public partial class Register : XncfRegisterBase, IXncfRegister
{
#region IRegister 接口
public override string Name => "Senparc.Xncf.XncfBuilder";
public override string Uid => "C2E1F87F-2DCE-4921-87CE-36923ED0D6EA";
public override string Version => "0.2.6";
public override string MenuName => "XNCF 模块生成器";
public override string Icon => "fa fa-plus";
public override string Description => "快速生成 XNCF 模块基础程序代码,或 Sample 演示,可基于基础代码扩展自己的应用";
#endregion
}
}
# [XncfOrder] 特性
您可以为 Register 类添加 [XncfOrder] 特性,来设置当前 XNCF 模块的载入次序。此特性构造函数内提供了排序的数字(order
参数),在系统载入时,按照降序排列(数字越大越在前),如:
[XncfRegister]
[XncfOrder(4090)]
public partial class Register : XncfRegisterBase, IXncfRegister
{
//...
}
order
参数约定:
0
:默认值,不提供 [XncfOrder] 特性的模块默认为 0,通常这样的模块载入顺序没有特别要求
1
~ 5000
:需要按照顺序预加载的重要模块
5000
以上:系统及基础模块,常规模块请勿占用
59xx
:系统底层基础模块,常规模块请勿占用
58xx
:AI 相关基础模,常规模块请勿占用块
# 更多可选接口
在已经实现了 IXncfRegister
接口的基础上,根据当前模块需要支持的功能,可以继续添加可选接口,扩充 Xncf 的能力。常用的可选接口有:
接口名称 | 支持功能 |
---|---|
IXncfFunction | 函数(Function),即最小化完成一个任务的方法 |
IXncfDatabase | 数据库,支持多数据库 |
IXncfRazorRuntimeCompilation | 包含网页时,对 RazorPage 进行运行时编译 |
IXncfMiddleware | 定义一个 .NET Core 的中间件(Middleware) |
IXncfThread | 支持后台线程 |
每个接口具体的定义和最终效果都会在后续开发中介绍。
# IXncfDatabase 接口(可选)
Register 类继承 IXncfDatabase 并实现接口方法后,即可激活数据库能力。
为了使代码更清晰,模板中的代码使用了“部分类(partial)”,相关代码独立储存在
Register.Database.cs
中(以下其他接口同理)。
模板默认代码如下:
public partial class Register : IXncfDatabase //注册 XNCF 模块数据库(按需选用)
{
#region IXncfDatabase 接口
/// <summary>
/// 数据库前缀
/// </summary>
public const string DATABASE_PREFIX = "Senparc_PromptRange_";
/// <summary>
/// 数据库前缀
/// </summary>
public string DatabaseUniquePrefix => DATABASE_PREFIX;
/// <summary>
/// 动态获取数据库上下文
/// </summary>
public Type TryGetXncfDatabaseDbContextType => MultipleDatabasePool.Instance.GetXncfDbContextType(this);
public void OnModelCreating(ModelBuilder modelBuilder)
{
//实现 [XncfAutoConfigurationMapping] 特性之后,可以自动执行,无需手动添加
//modelBuilder.ApplyConfiguration(new AreaTemplate_ColorConfigurationMapping());
}
public void AddXncfDatabaseModule(IServiceCollection services)
{
//DOT REMOVE OR MODIFY THIS LINE 请勿移除或修改本行 - Entities Point
//ex. services.AddScoped(typeof(Color));
}
#endregion
}
DATABASE_PREFIX
提供了一个数据库前缀的常量,默认的命名规则为”组织名字
模块名称
”,最终如:Senparc_PromptRange_
。
TryGetXncfDatabaseDbContextType
属性为特定方法,用于指定多数据库配置中当前数据库上下文类,默认代码无需修改。
OnModelCreating
方法将在 EF Core 数据库初始化时候执行(在 DbContext 的 OnModelCreating() 方法中执行)。
AddXncfDatabaseModule
用于配置针对数据库相关依赖注入配置。