依赖解析机制
SharwAPI 的插件加载器采用了一套严谨的依赖解析算法,确保在实例化任何插件之前,其依赖环境已经完全就绪。
加载流程概览
- 扫描 (Scan):
PluginLoader扫描指定目录下的所有 DLL 文件,通过反射读取实现了IApiPlugin接口的类型。此时仅读取元数据 (Metadata),不进行实例化。 - 构建图谱 (Graph Build): 根据所有插件的
Name和Dependencies属性,构建有向依赖图。 - 拓扑排序 (Topological Sort): 对依赖图进行排序,计算出正确的加载顺序。如果发现循环依赖 (A -> B -> A),加载过程将终止并报错。
- 验证 (Validation):
- 阶段一 (Declarative): 基于拓扑排序结果,检查强依赖是否存在及其版本范围。
- 阶段二 (Imperative): 对阶段一通过的插件调用
ValidateDependency方法进行自定义检查,传入已通过阶段一的有效候选插件列表。
- 初始化 (Initialization): 按排序后的顺序,依次调用
RegisterServices和Configure。
验证阶段详解
阶段一:声明式强依赖检查
这是基于 SemVer (语义化版本) 的静态检查。加载器会遍历每个插件的 Dependencies 字典。
- 输入: 插件定义的
Dependencies(Key: 插件名, Value: 版本范围字符串)。 - 逻辑:
- 检查目标插件是否存在于候选列表 (Candidate List) 中。
- 解析目标插件的
Version是否落在定义的范围内 (例如[1.0, 2.0))。
- 结果: 如果任何一个强依赖未满足,该插件将被标记为
Invalid,不参与后续加载。
阶段二:自定义逻辑验证
在声明式检查通过后,加载器会执行 ValidateDependency。
- 输入:
validPlugins(当前所有通过阶段一检查的有效插件及其版本)。 - 目的: 允许插件编写代码来处理无法用版本范围表达的逻辑。
- “如果插件A存在,但我需要它必须是特定的小版本,否则为了稳定性我选择不加载。”
- “我不兼容插件B,如果它存在,我拒绝加载。” (互斥)
- 机制: 此时插件已被实例化,但尚未注册服务或路由。如果返回
false,加载器将丢弃该插件实例。
设计哲学
将依赖检查前置到初始化之前,是为了保证 RegisterServices 执行时,您可以放心地使用 IDependencyInjection 注入依赖插件提供的服务,而无需担心空引用异常。