mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-25 01:16:35 +08:00
新增了卸载程序集的功能
This commit is contained in:
@@ -672,12 +672,12 @@ namespace Serein.Library.Api
|
|||||||
/// 从文件中加载Dll
|
/// 从文件中加载Dll
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dllPath"></param>
|
/// <param name="dllPath"></param>
|
||||||
void LoadDll(string dllPath);
|
void LoadLibrary(string dllPath);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除DLL
|
/// 移除DLL
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assemblyFullName">程序集的名称</param>
|
/// <param name="assemblyFullName">程序集的名称</param>
|
||||||
bool RemoteDll(string assemblyFullName);
|
bool UnloadLibrary(string assemblyFullName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清理加载的DLL(待更改)
|
/// 清理加载的DLL(待更改)
|
||||||
|
|||||||
@@ -520,7 +520,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
foreach (var dllPath in dllPaths)
|
foreach (var dllPath in dllPaths)
|
||||||
{
|
{
|
||||||
var dllFilePath = Path.GetFullPath(Path.Combine(filePath, dllPath));
|
var dllFilePath = Path.GetFullPath(Path.Combine(filePath, dllPath));
|
||||||
LoadDll(dllFilePath); // 加载项目文件时加载对应的程序集
|
LoadLibrary(dllFilePath); // 加载项目文件时加载对应的程序集
|
||||||
}
|
}
|
||||||
|
|
||||||
List<(NodeModelBase, string[])> regionChildNodes = new List<(NodeModelBase, string[])>();
|
List<(NodeModelBase, string[])> regionChildNodes = new List<(NodeModelBase, string[])>();
|
||||||
@@ -722,10 +722,20 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dllPath"></param>
|
/// <param name="dllPath"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void LoadDll(string dllPath)
|
public void LoadLibrary(string dllPath)
|
||||||
{
|
{
|
||||||
(var libraryInfo, var mdInfos) = FlowLibraryManagement.LoadLibrary(dllPath);
|
try
|
||||||
UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
{
|
||||||
|
(var libraryInfo, var mdInfos) = FlowLibraryManagement.LoadLibrary(dllPath);
|
||||||
|
if (mdInfos.Count > 0)
|
||||||
|
{
|
||||||
|
UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{ex}");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,7 +744,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assemblyName"></param>
|
/// <param name="assemblyName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool RemoteDll(string assemblyName)
|
public bool UnloadLibrary(string assemblyName)
|
||||||
{
|
{
|
||||||
return FlowLibraryManagement.UnloadLibrary(assemblyName);
|
return FlowLibraryManagement.UnloadLibrary(assemblyName);
|
||||||
|
|
||||||
|
|||||||
@@ -278,9 +278,9 @@ namespace Serein.NodeFlow.Env
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void LoadDll(string dllPath)
|
public void LoadLibrary(string dllPath)
|
||||||
{
|
{
|
||||||
currentFlowEnvironment.LoadDll(dllPath);
|
currentFlowEnvironment.LoadLibrary(dllPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadProject(FlowEnvInfo flowEnvInfo, string filePath)
|
public void LoadProject(FlowEnvInfo flowEnvInfo, string filePath)
|
||||||
@@ -307,9 +307,9 @@ namespace Serein.NodeFlow.Env
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool RemoteDll(string assemblyName)
|
public bool UnloadLibrary(string assemblyName)
|
||||||
{
|
{
|
||||||
return currentFlowEnvironment.RemoteDll(assemblyName);
|
return currentFlowEnvironment.UnloadLibrary(assemblyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RemoveConnectInvokeAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
public async Task<bool> RemoveConnectInvokeAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
||||||
|
|||||||
@@ -397,13 +397,13 @@ namespace Serein.NodeFlow.Env
|
|||||||
Console.WriteLine("远程环境尚未实现的接口:ExitRemoteEnv");
|
Console.WriteLine("远程环境尚未实现的接口:ExitRemoteEnv");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadDll(string dllPath)
|
public void LoadLibrary(string dllPath)
|
||||||
{
|
{
|
||||||
// 将dll文件发送到远程环境,由远程环境进行加载
|
// 将dll文件发送到远程环境,由远程环境进行加载
|
||||||
Console.WriteLine("远程环境尚未实现的接口:LoadDll");
|
Console.WriteLine("远程环境尚未实现的接口:LoadDll");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoteDll(string assemblyName)
|
public bool UnloadLibrary(string assemblyName)
|
||||||
{
|
{
|
||||||
// 尝试移除远程环境中的加载了的依赖
|
// 尝试移除远程环境中的加载了的依赖
|
||||||
Console.WriteLine("远程环境尚未实现的接口:RemoteDll");
|
Console.WriteLine("远程环境尚未实现的接口:RemoteDll");
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace Serein.NodeFlow
|
|||||||
this._assemblyFilePath = assemblyFilePath;
|
this._assemblyFilePath = assemblyFilePath;
|
||||||
this.assembly = assembly;
|
this.assembly = assembly;
|
||||||
this.actionOfUnloadAssmbly = actionOfUnloadAssmbly;
|
this.actionOfUnloadAssmbly = actionOfUnloadAssmbly;
|
||||||
LoadAssembly(assembly);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ namespace Serein.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assembly">程序集本身</param>
|
/// <param name="assembly">程序集本身</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private bool LoadAssembly(Assembly assembly)
|
public bool LoadAssembly(Assembly assembly)
|
||||||
{
|
{
|
||||||
#region 检查入参
|
#region 检查入参
|
||||||
|
|
||||||
@@ -122,13 +122,27 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
List<Type> types;
|
||||||
List<Type> types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型
|
try
|
||||||
if (types.Count < 0) // 防止动态程序集中没有类型信息?
|
|
||||||
{
|
{
|
||||||
|
types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型
|
||||||
|
if (types.Count < 0) // 防止动态程序集中没有类型信息?
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ReflectionTypeLoadException ex)
|
||||||
|
{
|
||||||
|
// 获取加载失败的类型
|
||||||
|
var loaderExceptions = ex.LoaderExceptions;
|
||||||
|
foreach (var loaderException in loaderExceptions)
|
||||||
|
{
|
||||||
|
Console.WriteLine(loaderException.Message);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -146,6 +160,15 @@ namespace Serein.NodeFlow
|
|||||||
// string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性
|
// string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性
|
||||||
foreach (var type in types)
|
foreach (var type in types)
|
||||||
{
|
{
|
||||||
|
if (type.Name.Equals("YoloFlowControl"))
|
||||||
|
{
|
||||||
|
//var ab = type.GetCustomAttribute<DynamicFlowAttribute>();
|
||||||
|
//var attributes = assembly.GetCustomAttributes();
|
||||||
|
//foreach (var attribute in attributes)
|
||||||
|
//{
|
||||||
|
// Console.WriteLine(attribute.GetType().Name);
|
||||||
|
//}
|
||||||
|
}
|
||||||
if (type.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute && dynamicFlowAttribute.Scan == true)
|
if (type.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute && dynamicFlowAttribute.Scan == true)
|
||||||
{
|
{
|
||||||
scanTypes.Add((type, dynamicFlowAttribute.Name));
|
scanTypes.Add((type, dynamicFlowAttribute.Name));
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using System.Reflection;
|
|||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Serein.NodeFlow.Tool
|
namespace Serein.NodeFlow.Tool
|
||||||
{
|
{
|
||||||
@@ -28,16 +29,18 @@ namespace Serein.NodeFlow.Tool
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存所有加载了的程序集
|
/// 缓存所有加载了的程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ConcurrentDictionary<string, FlowLibrary> _myFlowLibrarys = new ConcurrentDictionary<string, FlowLibrary>();
|
private readonly ConcurrentDictionary<string, FlowLibrary> _myFlowLibrarys = new ConcurrentDictionary<string, FlowLibrary>();
|
||||||
|
|
||||||
public (NodeLibraryInfo,List<MethodDetailsInfo>) LoadLibrary(string libraryfilePath)
|
public (NodeLibraryInfo, List<MethodDetailsInfo>) LoadLibrary(string libraryfilePath)
|
||||||
{
|
{
|
||||||
|
|
||||||
return LoadDllNodeInfo(libraryfilePath);
|
return LoadDllNodeInfo(libraryfilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UnloadLibrary(string libraryName)
|
public bool UnloadLibrary(string libraryName)
|
||||||
{
|
{
|
||||||
if (_myFlowLibrarys.TryGetValue(libraryName, out var flowLibrary))
|
libraryName = libraryName.Split(',')[0];
|
||||||
|
if (_myFlowLibrarys.Remove(libraryName, out var flowLibrary))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -64,10 +67,10 @@ namespace Serein.NodeFlow.Tool
|
|||||||
/// <param name="methodName">方法名称</param>
|
/// <param name="methodName">方法名称</param>
|
||||||
/// <param name="md">返回的方法描述</param>
|
/// <param name="md">返回的方法描述</param>
|
||||||
/// <returns>是否获取成功</returns>
|
/// <returns>是否获取成功</returns>
|
||||||
public bool TryGetMethodDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out MethodDetails md)
|
public bool TryGetMethodDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out MethodDetails md)
|
||||||
{
|
{
|
||||||
if(_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary)
|
if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary)
|
||||||
&& flowLibrary.MethodDetailss.TryGetValue(methodName,out md))
|
&& flowLibrary.MethodDetailss.TryGetValue(methodName, out md))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -85,7 +88,7 @@ namespace Serein.NodeFlow.Tool
|
|||||||
/// <param name="methodName">方法名称</param>
|
/// <param name="methodName">方法名称</param>
|
||||||
/// <param name="dd">返回的委托调用封装类</param>
|
/// <param name="dd">返回的委托调用封装类</param>
|
||||||
/// <returns>是否获取成功</returns>
|
/// <returns>是否获取成功</returns>
|
||||||
public bool TryGetDelegateDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out DelegateDetails dd)
|
public bool TryGetDelegateDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out DelegateDetails dd)
|
||||||
{
|
{
|
||||||
if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary)
|
if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary)
|
||||||
&& flowLibrary.DelegateDetailss.TryGetValue(methodName, out dd))
|
&& flowLibrary.DelegateDetailss.TryGetValue(methodName, out dd))
|
||||||
@@ -111,7 +114,7 @@ namespace Serein.NodeFlow.Tool
|
|||||||
|
|
||||||
foreach (var library in _myFlowLibrarys.Values)
|
foreach (var library in _myFlowLibrarys.Values)
|
||||||
{
|
{
|
||||||
var t_mds = library.MethodDetailss.Values.Where(it => it.MethodDynamicType == nodeType).ToList();
|
var t_mds = library.MethodDetailss.Values.Where(it => it.MethodDynamicType == nodeType).ToList();
|
||||||
mds.AddRange(t_mds);
|
mds.AddRange(t_mds);
|
||||||
}
|
}
|
||||||
return mds;
|
return mds;
|
||||||
@@ -124,13 +127,13 @@ namespace Serein.NodeFlow.Tool
|
|||||||
public Dictionary<RegisterSequence, List<Type>> GetaAutoRegisterType()
|
public Dictionary<RegisterSequence, List<Type>> GetaAutoRegisterType()
|
||||||
{
|
{
|
||||||
Dictionary<RegisterSequence, List<Type>> rsTypes = new Dictionary<RegisterSequence, List<Type>>();
|
Dictionary<RegisterSequence, List<Type>> rsTypes = new Dictionary<RegisterSequence, List<Type>>();
|
||||||
foreach(var library in _myFlowLibrarys.Values)
|
foreach (var library in _myFlowLibrarys.Values)
|
||||||
{
|
{
|
||||||
foreach(var kv in library.RegisterTypes)
|
foreach (var kv in library.RegisterTypes)
|
||||||
{
|
{
|
||||||
var @class = kv.Key;
|
var @class = kv.Key;
|
||||||
var type = kv.Value;
|
var type = kv.Value;
|
||||||
if(!rsTypes.TryGetValue(@class, out var tmpTypes))
|
if (!rsTypes.TryGetValue(@class, out var tmpTypes))
|
||||||
{
|
{
|
||||||
tmpTypes = new List<Type>();
|
tmpTypes = new List<Type>();
|
||||||
rsTypes.Add(@class, tmpTypes);
|
rsTypes.Add(@class, tmpTypes);
|
||||||
@@ -149,9 +152,10 @@ namespace Serein.NodeFlow.Tool
|
|||||||
public List<LibraryMds> GetAllLibraryMds()
|
public List<LibraryMds> GetAllLibraryMds()
|
||||||
{
|
{
|
||||||
List<LibraryMds> mds = new List<LibraryMds>();
|
List<LibraryMds> mds = new List<LibraryMds>();
|
||||||
foreach (FlowLibrary library in _myFlowLibrarys.Values)
|
foreach (FlowLibrary library in _myFlowLibrarys.Values)
|
||||||
{
|
{
|
||||||
var tmp = new LibraryMds {
|
var tmp = new LibraryMds
|
||||||
|
{
|
||||||
AssemblyName = library.FullName,
|
AssemblyName = library.FullName,
|
||||||
Mds = library.MethodDetailss.Values.Select(md => md.ToInfo()).ToArray()
|
Mds = library.MethodDetailss.Values.Select(md => md.ToInfo()).ToArray()
|
||||||
};
|
};
|
||||||
@@ -179,15 +183,48 @@ namespace Serein.NodeFlow.Tool
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从文件路径中加载程序集,返回相应的信息
|
/// 从文件路径中加载程序集,返回相应的信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dllPath"></param>
|
/// <param name="dllFilePath"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private (NodeLibraryInfo, List<MethodDetailsInfo>) LoadDllNodeInfo(string dllPath)
|
private (NodeLibraryInfo, List<MethodDetailsInfo>) LoadDllNodeInfo(string dllFilePath)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if true
|
||||||
|
var fileName = Path.GetFileName(dllFilePath); // 获取文件名
|
||||||
|
var dir = Path.GetDirectoryName(dllFilePath); // 获取目录路径
|
||||||
|
var sereinFlowLibraryPath = Path.Combine(dir, $"{nameof(Serein)}.{nameof(Serein.Library)}.dll");
|
||||||
|
// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
||||||
|
var flowAlc = new FlowLibraryAssemblyContext(sereinFlowLibraryPath, fileName);
|
||||||
|
Action actionUnload = () =>
|
||||||
|
{
|
||||||
|
flowAlc?.Unload(); // 卸载程序集
|
||||||
|
flowAlc = null;
|
||||||
|
GC.Collect(); // 强制触发GC确保卸载成功
|
||||||
|
GC.WaitForPendingFinalizers();
|
||||||
|
};
|
||||||
|
var assembly = flowAlc.LoadFromAssemblyPath(dllFilePath); // 加载指定路径的程序集
|
||||||
|
if (_myFlowLibrarys.ContainsKey(assembly.GetName().Name))
|
||||||
|
{
|
||||||
|
actionUnload.Invoke();
|
||||||
|
throw new Exception($"程序集[{assembly.GetName().FullName}]已经加载过!");
|
||||||
|
}
|
||||||
|
|
||||||
var fileName = Path.GetFileName(dllPath); // 获取文件名
|
FlowLibrary flowLibrary = new FlowLibrary(dllFilePath, assembly, actionUnload);
|
||||||
Assembly assembly = Assembly.LoadFrom(dllPath); // 加载程序集
|
if (flowLibrary.LoadAssembly(assembly))
|
||||||
FlowLibrary flowLibrary = new FlowLibrary(dllPath, assembly, () =>
|
{
|
||||||
|
_myFlowLibrarys.TryAdd(assembly.GetName().Name, flowLibrary);
|
||||||
|
(NodeLibraryInfo, List<MethodDetailsInfo>) result = (flowLibrary.ToInfo(),
|
||||||
|
flowLibrary.MethodDetailss.Values.Select(md => md.ToInfo()).ToList());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"程序集[{assembly.GetName().FullName}]加载失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
var fileName = Path.GetFileName(dllFilePath); // 获取文件名
|
||||||
|
Assembly assembly = Assembly.LoadFrom(dllFilePath); // 加载程序集
|
||||||
|
FlowLibrary flowLibrary = new FlowLibrary(dllFilePath, assembly, () =>
|
||||||
{
|
{
|
||||||
Console.WriteLine("暂未实现卸载程序集");
|
Console.WriteLine("暂未实现卸载程序集");
|
||||||
//flowAlc.Unload(); // 卸载程序集
|
//flowAlc.Unload(); // 卸载程序集
|
||||||
@@ -203,62 +240,72 @@ namespace Serein.NodeFlow.Tool
|
|||||||
return result;
|
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
|
#endif
|
||||||
//if (OperatingSystem.IsWindows())
|
|
||||||
//{
|
|
||||||
// UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
|
||||||
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// 是否对程序集的引用
|
|
||||||
///// </summary>
|
|
||||||
//public void UnloadPlugin()
|
|
||||||
//{
|
|
||||||
// _pluginAssembly = null; // 释放对程序集的引用
|
|
||||||
// Unload(); // 触发卸载
|
|
||||||
// // 强制进行垃圾回收,以便完成卸载
|
|
||||||
// GC.Collect();
|
|
||||||
// GC.WaitForPendingFinalizers();
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 流程依赖加载
|
||||||
|
/// </summary>
|
||||||
|
public class FlowLibraryAssemblyContext : AssemblyLoadContext
|
||||||
|
{
|
||||||
|
private readonly AssemblyDependencyResolver _resolver;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建新的加载上下文
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sereinFlowLibraryPath">类库主</param>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
public FlowLibraryAssemblyContext(string sereinFlowLibraryPath, string name) : base(name, isCollectible: true)
|
||||||
|
{
|
||||||
|
_resolver = new AssemblyDependencyResolver(sereinFlowLibraryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Assembly? Load(AssemblyName assemblyName)
|
||||||
|
{
|
||||||
|
string? assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
|
||||||
|
if (!string.IsNullOrEmpty(assemblyPath))
|
||||||
|
{
|
||||||
|
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
|
||||||
|
//var assembly = LoadFromAssemblyPath(assemblyPath);
|
||||||
|
return assembly;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Default.Assemblies.FirstOrDefault(x => x.FullName == assemblyName.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 构建依赖项的路径
|
||||||
|
//string assemblyPath = Path.Combine(AppContext.BaseDirectory, assemblyName.Name + ".dll");
|
||||||
|
//if (File.Exists(assemblyPath))
|
||||||
|
//{
|
||||||
|
// return LoadFromAssemblyPath(assemblyPath);
|
||||||
|
//}
|
||||||
|
//assemblyPath = Path.Combine(filePath, assemblyName.Name + ".dll");
|
||||||
|
//if (File.Exists(assemblyPath))
|
||||||
|
//{
|
||||||
|
// return LoadFromAssemblyPath(assemblyPath);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//return null; // 如果没有找到,返回 null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static class PluginAssemblyContextExtensions
|
||||||
|
{
|
||||||
|
|
||||||
|
public static Assembly FromAssemblyPath(this AssemblyLoadContext context, string path)
|
||||||
|
{
|
||||||
|
|
||||||
|
return context.LoadFromAssemblyPath(path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ namespace Serein.Workbench
|
|||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
menu.Items.Add(CreateMenuItem("卸载", (s, e) =>
|
menu.Items.Add(CreateMenuItem("卸载", (s, e) =>
|
||||||
{
|
{
|
||||||
if (this.EnvDecorator.RemoteDll(nodeLibraryInfo.AssemblyName))
|
if (this.EnvDecorator.UnloadLibrary(nodeLibraryInfo.AssemblyName))
|
||||||
{
|
{
|
||||||
DllStackPanel.Children.Remove(dllControl);
|
DllStackPanel.Children.Remove(dllControl);
|
||||||
}
|
}
|
||||||
@@ -1165,7 +1165,7 @@ namespace Serein.Workbench
|
|||||||
{
|
{
|
||||||
if (file.EndsWith(".dll"))
|
if (file.EndsWith(".dll"))
|
||||||
{
|
{
|
||||||
EnvDecorator.LoadDll(file);
|
EnvDecorator.LoadLibrary(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user