🔌 PluginOperate — 插件热加载
命名空间: Snet.Core.plugin | 继承: CoreUnify<PluginOperate, string> | 源码: Snet.Core/plugin/
基于 AssemblyLoadContext(isCollectible = true)实现运行时插件加载/卸载。支持 DLL 热插拔,无需重启应用。
PluginOperate API
插件发现与加载
// 扫描目录并初始化插件
public List<(PluginModel Model, object? Param)> InitPlugin(string path, string interfaceFullName)
public async Task<List<(PluginModel Model, object? Param)>> InitPluginAsync(...)
// 按 className 创建插件实例
public async Task<T?> CreateAsync<T>(string className, string param, PluginType type)
查询
public int LoadedPluginCount // 已加载插件数
public IReadOnlyCollection<string> LoadedPluginNames // 已加载插件名列表
public bool IsPluginLoaded(string className) // 检查是否已加载
public string GetPluginPath(string className) // 获取插件路径
public string GetVersion(string className) // 获取版本
public string GetPluginDiagnostics(string className) // 获取诊断信息
获取插件对象
public T? GetPluginInterfaceObject<T>(string className) where T : class
public object? GetPluginParamObject(string interfaceFullName, string className)
public object? ConvertPluginJsonParam(string className, string jsonContent)
卸载
public async Task<bool> RemovePluginAsync(string className, CancellationToken token)
public async Task RemovePluginsAsync(CancellationToken token) // 卸载全部
验证
public async Task<OperateResult> StatusVerifyAsync(string interfaceFullName,
string className, string data, CancellationToken token)
PluginLoadContext — 插件加载上下文
内部类 | 继承: AssemblyLoadContext
public PluginLoadContext(string pluginPath, long maxAssemblySizeBytes = 50 * 1024 * 1024)
public int LoadedAssemblyCount
public Assembly LoadFromFileStream(string assemblyPath)
public async Task<Assembly> LoadFromFileStreamAsync(string assemblyPath, CancellationToken token)
public bool IsFullyUnloaded() // 检查 ALC 是否已完全卸载
关键设计
isCollectible = true— 允许 GC 回收整个 ALC- 内存流加载 — 无文件锁
- 大小限制 50MB — 防止恶意超大程序集
- 路径沙箱 — 尾部分隔符验证,防止路径穿越
使用模式
var plugin = new PluginOperate();
// 1. 初始化 — 扫描 plugins/ 目录,加载所有 IDaq 实现
var plugins = plugin.InitPlugin("./plugins", "Snet.Model.interface.IDaq");
// 2. 获取插件实例
var siemensPlugin = plugin.GetPluginInterfaceObject<IDaq>("SiemensOperate");
// 3. 通过 JSON 配置创建
var instance = await plugin.CreateAsync<IDaq>("SiemensOperate",
"{\"IpAddress\":\"192.168.1.100\",\"Port\":102}", PluginType.Daq);
// 4. 卸载
await plugin.RemovePluginAsync("SiemensOperate");
