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();
//}
}
}