using Serein.Library; using Serein.Library.Api; using Serein.Library.FlowNode; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.Loader; using System.Text; using System.Threading.Tasks; namespace Serein.NodeFlow.Tool { /// /// 管理加载在运行环境中的外部程序集 /// public class FlowLibraryManagement { public FlowLibraryManagement(IFlowEnvironment flowEnvironment) { this.flowEnvironment = flowEnvironment; } private readonly IFlowEnvironment flowEnvironment; /// /// 缓存所有加载了的程序集 /// private ConcurrentDictionary _myFlowLibrarys = new ConcurrentDictionary(); public (NodeLibraryInfo,List) LoadLibrary(string libraryfilePath) { return LoadDllNodeInfo(libraryfilePath); } public bool UnloadLibrary(string libraryName) { if (_myFlowLibrarys.TryGetValue(libraryName, out var flowLibrary)) { try { flowLibrary.Upload(); return true; } catch (Exception ex) { Console.WriteLine($"尝试卸载程序集[{libraryName}]发生错误:{ex}"); return false; } } else { return false; } } /// /// 获取方法描述 /// /// 程序集名称 /// 方法名称 /// 返回的方法描述 /// 是否获取成功 public bool TryGetMethodDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out MethodDetails md) { if(_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary) && flowLibrary.MethodDetailss.TryGetValue(methodName,out md)) { return true; } else { md = null; return false; } } /// /// 获取方法调用的委托 /// /// 程序集名称 /// 方法名称 /// 返回的委托调用封装类 /// 是否获取成功 public bool TryGetDelegateDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out DelegateDetails dd) { if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary) && flowLibrary.DelegateDetailss.TryGetValue(methodName, out dd)) { return true; } else { dd = null; return false; } } /// /// 获取(初始化/加载时/退出后)相应的节点方法 /// /// /// public List GetMdsOnFlowStart(NodeType nodeType) { List mds = []; foreach (var library in _myFlowLibrarys.Values) { var t_mds = library.MethodDetailss.Values.Where(it => it.MethodDynamicType == nodeType).ToList(); mds.AddRange(t_mds); } return mds; } /// /// 获取流程启动时在不同时间点需要自动实例化的类型 /// /// public Dictionary> GetaAutoRegisterType() { Dictionary> rsTypes = new Dictionary>(); foreach(var library in _myFlowLibrarys.Values) { foreach(var kv in library.RegisterTypes) { var @class = kv.Key; var type = kv.Value; if(!rsTypes.TryGetValue(@class, out var tmpTypes)) { tmpTypes = new List(); rsTypes.Add(@class, tmpTypes); } tmpTypes.AddRange(type); } } return rsTypes; } /// /// 获取所有方法信息,用于保存项目时调用 /// /// public List GetAllLibraryMds() { List mds = new List(); foreach (FlowLibrary library in _myFlowLibrarys.Values) { var tmp = new LibraryMds { AssemblyName = library.FullName, Mds = library.MethodDetailss.Values.Select(md => md.ToInfo()).ToArray() }; mds.Add(tmp); } return mds; } /// /// 序列化当前项目的依赖信息、节点信息,用于远程登录的场景,需要将依赖信息从本地(受控端)发送到远程(主控端) /// /// public List GetAllLibraryInfo() { return _myFlowLibrarys.Values.Select(library => library.ToInfo()).ToList(); } #region 功能性方法 /// /// 从文件路径中加载程序集,返回相应的信息 /// /// /// private (NodeLibraryInfo, List) LoadDllNodeInfo(string dllPath) { var fileName = Path.GetFileName(dllPath); // 获取文件名 Assembly assembly = Assembly.LoadFrom(dllPath); // 加载程序集 FlowLibrary flowLibrary = new FlowLibrary(dllPath, assembly, () => { Console.WriteLine("暂未实现卸载程序集"); //flowAlc.Unload(); // 卸载程序集 //flowAlc = null; //GC.Collect(); // 强制触发GC确保卸载成功 //GC.WaitForPendingFinalizers(); }); _myFlowLibrarys.TryAdd(assembly.GetName().Name, flowLibrary); (NodeLibraryInfo, List) result = (flowLibrary.ToInfo(), flowLibrary.MethodDetailss.Values.Select(md => md.ToInfo()).ToList()); return result; #if false var fileName = Path.GetFileName(dllPath); // 获取文件名 var flowAlc = new AssemblyLoadContext(fileName, true); flowAlc.LoadFromAssemblyPath(dllPath); // 加载指定路径的程序集 flowAlc.LoadFromAssemblyPath(@"F:\临时\project\yolo flow\OpenCvSharp.dll"); // 加载指定路径的程序集 var assemblt = flowAlc.Assemblies.ToArray()[0]; // 目前只会加载一个程序集,所以这样获取 FlowLibrary flowLibrary = new FlowLibrary(dllPath, assemblt, () => { flowAlc.Unload(); // 卸载程序集 flowAlc = null; GC.Collect(); // 强制触发GC确保卸载成功 GC.WaitForPendingFinalizers(); }); _myFlowLibrarys.TryAdd(assemblt.GetName().Name, flowLibrary); return flowLibrary.ToInfo(); //foreach (var assemblt in flowAlc.Assemblies) //{ // FlowLibrary flowLibrary = new FlowLibrary(dllPath, assemblt, () => // { // flowAlc.Unload(); // 卸载程序集 // flowAlc = null; // GC.Collect(); // 强制触发GC确保卸载成功 // GC.WaitForPendingFinalizers(); // }); //} #endif //if (OperatingSystem.IsWindows()) //{ // UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibraryInfo, mdInfos))); // 通知UI创建dll面板显示 //} } #endregion ///// ///// 是否对程序集的引用 ///// //public void UnloadPlugin() //{ // _pluginAssembly = null; // 释放对程序集的引用 // Unload(); // 触发卸载 // // 强制进行垃圾回收,以便完成卸载 // GC.Collect(); // GC.WaitForPendingFinalizers(); //} } }