For the complete documentation index, see llms.txt. This page is also available as Markdown.

基础概念与协作方式

区分宿主、插件、模块、服务、提供者、构件和四类元数据文件。

本页以“论坛模块提供主题查询接口”为例,说明框架中的几个相似名词。先分清这些概念,再读配置和代码,会更容易判断一个问题发生在哪个环节。

宿主与内容根

宿主是启动应用的进程入口,例如终端、后台服务和 Web 应用。内容根是应用查找配置、插件等内容的基准目录。用绝对路径启动 DLL,并不会自动把当前工作目录切换到 DLL 所在目录。

因此,部署后应进入运行目录再启动,或通过宿主配置明确内容根。找不到 plugins/ 时,先检查内容根,不要立即改业务程序集。

插件与程序集

程序集包含可执行的 .NET 类型。插件由 .plugin 清单描述,声明依赖、程序集和扩展点;一个插件可以包含多个程序集,也可以只贡献装配配置。

项目引用让编译器看见类型;插件清单让运行时知道加载什么;部署文件让必要的文件出现在正确位置。这三个环节互不替代。比如 Discussions.Web 项目能编译,但漏部署 Zongsoft.Discussions.Web.plugin,运行时仍不会按清单加载其控制器。

插件树与构件

插件树是运行时扩展点的路径结构。一个插件可以向已有路径追加构件,不需要修改路径拥有者的源码。例如 Discussions 向数据验证器扩展点添加站点验证器,数据驱动向 /Workbench/Data/Drivers 添加驱动。

构件是插件树上的可构建定义。构建器决定如何创建对象,解析器解释属性中的表达式。下面的真实清单创建 Discussions 数据验证器,并将它挂到数据扩展点。

来源:src/Zongsoft.Discussions.plugin(节选;上下文见源文件)。

Zongsoft.Discussions.plugin
<extension path="/Workbench/Data/Validators">
	<object name="Discussions" type="Zongsoft.Discussions.Data.DataValidator, Zongsoft.Discussions" />
</extension>

构件名称是树节点名称,不自动成为 DI 中的服务别名。文件目录也不是插件树路径。详细语法见构件与服务。

模块、服务与提供者

模块表达应用中的业务边界,例如 Discussions。一个模块可以由几个插件共同提供;插件加载也不会自动为每个插件创建业务模块。应用自行定义模块;需要将模块纳入应用模块集合时,可把模块对象挂载到 /Workbench/Modules。

💡 把模块挂载到 /Workbench/Modules 等同于加入到 ApplicationContext.Current.Modules 集合,虽然这不是必须的,但统一归拢的模块集有利于系统提供通用一致的模块化能力输出。譬如 Zongsoft.Web.OpenApi 就会使用应用模块集进行 API 文档的模块化分类。

服务是通过契约提供某种操作的对象。服务容器负责按类型、别名或匹配参数解析这些对象。模块容器优先查找模块服务,再回退应用共享服务;其生命周期不等于 Web 请求生命周期。

提供者解决另一类问题:某一实现需要按名称供应多个实例。例如 Redis 提供者可以按连接名返回不同缓存。此时先选提供者,再取具名实例。

名称
示例
决定什么

插件名

Zongsoft.Externals.Redis

清单依赖指向哪个插件

模块名

Discussions

模块服务解析域

提供者名

Redis

由哪种实现创建或查找实例

连接/实例名

由实际环境选项定义

采用哪一组连接参数

构件名

Discussions 验证器节点

插件树中对象的位置

配置、映射与部署

文件
回答的问题
读取者

.plugin

加载哪些程序集?向哪里贡献对象?

插件框架

.option

采用什么连接、参数和运行选项?

配置提供程序

.mapping

业务实体如何对应数据源?

数据引擎元数据加载器

.deploy

哪些文件或包复制到哪里?

部署工具

Discussions 插件的清单可以保持稳定,测试和生产环境使用不同连接配置。部署方案决定是否包含 Redis 和 MySQL,运行配置决定使用哪个已部署实现及连接。配置中的名称必须与注册、连接项和业务调用形成一致关系。

.option 并非任意放进目录就会加载。插件配置与已加载清单的文件主名关联,详见选项配置文件。

工作器、初始化器与普通服务

初始化器用于应用初始化阶段的配置或装配;工作器用于需要启动、持续运行并在关闭时停止的任务;普通服务用于按调用执行某项操作。将“订阅消息并保持监听”写进构造函数,会让对象装配、外部连接和故障处理纠缠在一起,通常应交由工作器管理。

通过服务特性扫描注册的普通类型默认是单例。共享实例的创建与释放由注册和提供者约定决定。需要每次调用独立状态时,应明确作用域或使用工厂,不要从“具名”“模块化”推导出“每次新建”。

插件化的适用边界

插件化适合按业务能力拆分、按环境组合基础设施、让多个宿主复用业务。它也要求团队维护公共契约、清单、配置及部署兼容性;一个非常小的独立程序未必需要全部机制。

继续阅读:设计理念、插件应用模型、术语表。

最后更新于