> For the complete documentation index, see [llms.txt](https://docs.zongsoft.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zongsoft.com/overview/concepts.md).

# 基础概念与协作方式

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

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

## 宿主与内容根 <a href="#host" id="host"></a>

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

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

## 插件与程序集 <a href="#plugin" id="plugin"></a>

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

项目引用让编译器看见类型；插件清单让运行时知道加载什么；部署文件让必要的文件出现在正确位置。这三个环节互不替代。比如 [Discussions.Web](https://github.com/Zongsoft/discussions/tree/main/src/api) 项目能编译，但漏部署 [Zongsoft.Discussions.Web.plugin](https://github.com/Zongsoft/discussions/blob/main/src/api/Zongsoft.Discussions.Web.plugin)，运行时仍不会按清单加载其控制器。

## 插件树与构件 <a href="#plugin-tree" id="plugin-tree"></a>

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

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

来源：[src/Zongsoft.Discussions.plugin](https://github.com/Zongsoft/Zongsoft.Discussions/blob/main/src/Zongsoft.Discussions.plugin#L31)（节选；上下文见源文件）。

{% code title="Zongsoft.Discussions.plugin" %}

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

{% endcode %}

构件名称是树节点名称，不自动成为 DI 中的服务别名。文件目录也不是插件树路径。详细语法见[构件与服务](/framework/plugins/builtins-and-services.md)。

## 模块、服务与提供者 <a href="#module-service-provider" id="module-service-provider"></a>

**模块**表达应用中的业务边界，例如 Discussions。一个模块可以由几个插件共同提供；插件加载也不会自动为每个插件创建业务模块。应用自行定义模块；需要将模块纳入[应用模块](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/src/Services/IApplicationModule.cs)集合时，可把模块对象挂载到 `/Workbench/Modules`。

> 💡 把模块挂载到 `/Workbench/Modules` 等同于加入到 [`ApplicationContext.Current.Modules`](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/src/Services/ApplicationContext.cs) 集合，虽然这不是必须的，但统一归拢的模块集有利于系统提供通用一致的模块化能力输出。譬如 [Zongsoft.Web.OpenApi](https://github.com/Zongsoft/framework/tree/main/Zongsoft.Web/openapi) 就会使用[应用模块](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/src/Services/IApplicationModule.cs)集进行 API 文档的模块化分类。

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

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

| 名称     | 示例                         | 决定什么         |
| ------ | -------------------------- | ------------ |
| 插件名    | `Zongsoft.Externals.Redis` | 清单依赖指向哪个插件   |
| 模块名    | `Discussions`              | 模块服务解析域      |
| 提供者名   | `Redis`                    | 由哪种实现创建或查找实例 |
| 连接/实例名 | 由实际环境选项定义                  | 采用哪一组连接参数    |
| 构件名    | `Discussions` 验证器节点        | 插件树中对象的位置    |

{% hint style="warning" %}
🚨 服务定位表达式中的提供者与插件表达式指定的模块容器不是同一概念，名称不能互换。完整规则见[服务定位与所有权](/framework/core/services/locating.md)。
{% endhint %}

## 配置、映射与部署 <a href="#metadata" id="metadata"></a>

| 文件         | 回答的问题            | 读取者        |
| ---------- | ---------------- | ---------- |
| `.plugin`  | 加载哪些程序集？向哪里贡献对象？ | 插件框架       |
| `.option`  | 采用什么连接、参数和运行选项？  | 配置提供程序     |
| `.mapping` | 业务实体如何对应数据源？     | 数据引擎元数据加载器 |
| `.deploy`  | 哪些文件或包复制到哪里？     | 部署工具       |

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

`.option` 并非任意放进目录就会加载。插件配置与已加载清单的文件主名关联，详见[选项配置文件](/references/option-files.md)。

## 工作器、初始化器与普通服务 <a href="#lifetime" id="lifetime"></a>

[初始化器](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/src/Services/IApplicationInitializer.cs)用于应用初始化阶段的配置或装配；[工作器](https://github.com/Zongsoft/framework/blob/main/Zongsoft.Core/src/Components/IWorker.cs)用于需要启动、持续运行并在关闭时停止的任务；普通服务用于按调用执行某项操作。将“订阅消息并保持监听”写进构造函数，会让对象装配、外部连接和故障处理纠缠在一起，通常应交由工作器管理。

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

## 插件化的适用边界

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

{% hint style="warning" %}
🚨 插件在宿主进程中以宿主权限执行。模块边界、插件目录和服务名称都不构成安全沙箱；配置变更通知也不代表程序集能够安全热替换。更换 DLL 后应按应用的停止、部署、启动流程验证。
{% endhint %}

继续阅读：[设计理念](/overview/conception.md)、[插件应用模型](/framework/plugins/application-model.md)、[术语表](/references/glossary.md)。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.zongsoft.com/overview/concepts.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
