Skip to content

依赖解析机制

SharwAPI 的插件加载器采用了一套严谨的依赖解析算法,确保在实例化任何插件之前,其依赖环境已经完全就绪。

加载流程概览

  1. 扫描 (Scan): PluginLoader 扫描指定目录下的所有 DLL 文件,通过反射读取实现了 IApiPlugin 接口的类型。此时仅读取元数据 (Metadata),不进行实例化。
  2. 构建图谱 (Graph Build): 根据所有插件的 NameDependencies 属性,构建有向依赖图。
  3. 拓扑排序 (Topological Sort): 对依赖图进行排序,计算出正确的加载顺序。如果发现循环依赖 (A -> B -> A),加载过程将终止并报错。
  4. 验证 (Validation):
    • 阶段一 (Declarative): 基于拓扑排序结果,检查强依赖是否存在及其版本范围。
    • 阶段二 (Imperative): 对阶段一通过的插件调用 ValidateDependency 方法进行自定义检查,传入已通过阶段一的有效候选插件列表。
  5. 初始化 (Initialization): 按排序后的顺序,依次调用 RegisterServicesConfigure

验证阶段详解

阶段一:声明式强依赖检查

这是基于 SemVer (语义化版本) 的静态检查。加载器会遍历每个插件的 Dependencies 字典。

  • 输入: 插件定义的 Dependencies (Key: 插件名, Value: 版本范围字符串)。
  • 逻辑:
    • 检查目标插件是否存在于候选列表 (Candidate List) 中。
    • 解析目标插件的 Version 是否落在定义的范围内 (例如 [1.0, 2.0) )。
  • 结果: 如果任何一个强依赖未满足,该插件将被标记为 Invalid,不参与后续加载。

阶段二:自定义逻辑验证

在声明式检查通过后,加载器会执行 ValidateDependency

  • 输入: validPlugins (当前所有通过阶段一检查的有效插件及其版本)。
  • 目的: 允许插件编写代码来处理无法用版本范围表达的逻辑。
    • “如果插件A存在,但我需要它必须是特定的小版本,否则为了稳定性我选择不加载。”
    • “我不兼容插件B,如果它存在,我拒绝加载。” (互斥)
  • 机制: 此时插件已被实例化,但尚未注册服务或路由。如果返回 false,加载器将丢弃该插件实例。

设计哲学

将依赖检查前置到初始化之前,是为了保证 RegisterServices 执行时,您可以放心地使用 IDependencyInjection 注入依赖插件提供的服务,而无需担心空引用异常。