Files
StoreWeb/Plugins/README.md
T

87 lines
5.2 KiB
Markdown

# 独立功能插件
`Modules/` 放置商城业务模块,`Plugins/` 放置共用 API 宿主的独立功能。
插件通过 IModule、IStartup 和依赖标记接口接入现有生命周期,控制器共用宿主 URL。
## 发布和运行
在仓库根目录执行生成命令:
```powershell
dotnet build Store.API/Store.Api.csproj -c Release
dotnet build Plugins/CloudProduct/Store.CloudProduct.csproj -c Release
dotnet build Plugins/Store.ImageCache/Store.ImageCache.csproj -c Release
dotnet Bin/Store.Api.dll
```
API 直接生成到仓库根目录 `Bin/`,不再附加配置名称、目标框架或运行时子目录。
各插件生成后自动将自身完整输出(DLL、deps.json、配置、运行依赖及 runtimes 子目录)复制到
`Bin/Plugins/<项目名>/`。例如:
```text
Bin/
Store.Api.dll
Store.Api.deps.json
Store.Api.runtimeconfig.json
appsettings.json
Plugins/
Store.CloudProduct/
Store.ImageCache/
```
生成全部所需项目后即可整体拷贝 `Bin/` 部署,目标机器需要兼容的 .NET/ASP.NET Core 运行时。
API 不引用插件,也不会在单独生成 API 时触发插件构建;生成插件项目或生成包含插件的解决方案时会自动复制。
未来在 Plugins 下新增项目会继承同目录的 Directory.Build.props/targets,无需逐个添加复制任务。
Debug 与 Release 共用此目录;部署前应以相同配置重新生成宿主及所需插件。
生成宿主或插件后,都会按相对路径和 SHA-256 清理与宿主完全相同的插件文件;同名但内容不同的文件保留。
宿主尚未生成时插件暂时保留完整依赖,之后生成宿主会自动去重。去重后的插件目录必须与匹配的宿主一起部署。
同一插件输出和部署子目录中的旧入口(其他名称的 .deps.json 及对应 DLL、PDB、runtimeconfig.json)会在生成时自动清理,避免重复加载重命名前的插件。每个部署子目录只放一个插件入口。
其他旧文件不会自动删除;插件部署目录更名、删除或移除依赖后,应清理对应旧目录再生成。
MSBuild 属性 `StoreHostOutputPath` 可覆盖此路径,覆盖时使用绝对目录并以目录分隔符结尾。
需要标准 publish 产物时也可以指定独立部署目录:
```powershell
dotnet publish Store.API/Store.Api.csproj -c Release -o artifacts/server
dotnet publish Plugins/CloudProduct/Store.CloudProduct.csproj -c Release -o artifacts/server/Plugins/Store.CloudProduct
dotnet publish Plugins/Store.ImageCache/Store.ImageCache.csproj -c Release -o artifacts/server/Plugins/Store.ImageCache
```
宿主配置 `Plugins:Path` 默认为 `Plugins`,相对路径以宿主二进制目录为基准,也可使用绝对路径。
可以通过环境变量 `Plugins__Path` 覆盖。目录不存在或为空时不加载插件。
每个插件子目录包含入口 DLL、同名 `.deps.json`、配置和宿主未提供的依赖;共享依赖由宿主提供。
上面的标准 `dotnet publish -o` 命令仍生成完整独立发布内容,仅 `Bin/Plugins/` 自动执行宿主去重。
加载器递归寻找 `.deps.json`,由 `StoreHubAppTypeFinder.cs` 中现有 Match/AvailablePrefix 过滤入口程序集。
依赖解析不受入口名称过滤限制。两个现有插件从自身程序集所在目录读取 JSON 配置。
## 新增与更新
新增插件无需修改 Store.API:创建类库,引用共享框架,实现需要的模块/启动接口,启用
`EnableDynamicLoading`,并将配置设置为复制到输出和发布目录;生成后会自动复制到宿主扫描目录;也可以独立发布到其他扫描目录。
配置文件命名与配置节应避免和其他插件冲突。现有模块的配置合并顺序保持不变。
插件、宿主和共享契约必须使用兼容版本。所有程序集加载到默认上下文,同名程序集只加载一次;
发布目录中同名依赖身份不一致会在加载时明确报错,不提供依赖版本隔离。
插件必需的程序集、类型或配置缺失时启动失败;未调用的第三方可选功能依赖可能在调用时才解析。
插件与宿主同进程运行,共用认证、容器和中间件。更新时替换完整发布目录并重启宿主;
不支持热加载、卸载和进程隔离。CloudProduct 仍需要其数据库、OpenSearch 和后台任务配置。
## 加载冒烟验证
验证程序不连接数据库或 OpenSearch;每个场景单独启动进程:
```powershell
dotnet run --project Tests/PluginLoadingSmoke -- <插件根目录>
dotnet run --project Tests/PluginLoadingSmoke -- <仅包含ImageCache的发布目录> image
dotnet run --project Tests/PluginLoadingSmoke -- <空目录或不存在目录> empty
dotnet run --project Tests/PluginLoadingSmoke -- - empty
dotnet run --project Tests/PluginLoadingSmoke -- <缺依赖或包含版本冲突的目录> failure
```
`-` 使用默认 Plugins 路径;默认路径下已部署插件时使用普通模式。
普通模式验证两个插件及控制器发现和程序集去重;`image` 额外验证真实框架注册流程中的配置、DI、IStartup 和 MVC。
将同一插件发布内容复制到另一子目录可验证重复程序集;缺失依赖和版本冲突应报告具体插件路径。