mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-19 16:06:33 +08:00
环境接口新增了加载项目文件路径,方便类库在Init事件中自动加载具体的依赖
This commit is contained in:
@@ -231,6 +231,12 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
public string EnvName { get; set; } = SpaceName;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 本地加载的项目文件路径
|
||||
/// </summary>
|
||||
public string ProjectFileLocation { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否全局中断
|
||||
/// </summary>
|
||||
@@ -526,6 +532,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="filePath"></param>
|
||||
public void LoadProject(FlowEnvInfo flowEnvInfo, string filePath)
|
||||
{
|
||||
this.ProjectFileLocation = filePath;
|
||||
var projectData = flowEnvInfo.Project;
|
||||
// 加载项目配置文件
|
||||
var dllPaths = projectData.Librarys.Select(it => it.FilePath).ToList();
|
||||
@@ -542,8 +549,8 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
_ = Task.Run( async () =>
|
||||
{
|
||||
await LoadNodeInfosAsync(projectData.Nodes.ToList());
|
||||
await SetStartNodeAsync(projectData.StartNode);
|
||||
await LoadNodeInfosAsync(projectData.Nodes.ToList()); // 加载节点信息
|
||||
await SetStartNodeAsync(projectData.StartNode); // 设置起始节点
|
||||
});
|
||||
|
||||
}
|
||||
@@ -651,7 +658,7 @@ namespace Serein.NodeFlow.Env
|
||||
public bool TryUnloadLibrary(string assemblyName)
|
||||
{
|
||||
// 获取与此程序集相关的节点
|
||||
var groupedNodes = NodeModels.Values.Where(node => node.MethodDetails.AssemblyName.Equals(assemblyName)).ToArray();
|
||||
var groupedNodes = NodeModels.Values.Where(node => !string.IsNullOrWhiteSpace(node.MethodDetails.AssemblyName) && node.MethodDetails.AssemblyName.Equals(assemblyName)).ToArray();
|
||||
if (groupedNodes.Length == 0)
|
||||
{
|
||||
var isPass = FlowLibraryManagement.UnloadLibrary(assemblyName);
|
||||
@@ -1411,6 +1418,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <returns></returns>
|
||||
public bool LoadNativeLibraryOfRuning(string file)
|
||||
{
|
||||
|
||||
return NativeDllHelper.LoadDll(file);
|
||||
}
|
||||
|
||||
@@ -1421,7 +1429,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="isRecurrence">是否递归加载</param>
|
||||
public void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true)
|
||||
{
|
||||
NativeDllHelper.LoadAllDll(path, isRecurrence);
|
||||
NativeDllHelper.LoadAllDll(path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -87,6 +87,7 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
|
||||
public string EnvName => currentFlowEnvironment.EnvName;
|
||||
public string ProjectFileLocation => currentFlowEnvironment.EnvName;
|
||||
|
||||
public bool IsGlobalInterrupt => currentFlowEnvironment.IsGlobalInterrupt;
|
||||
|
||||
|
||||
@@ -65,6 +65,10 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
public string EnvName => FlowEnvironment.SpaceName;
|
||||
|
||||
/// <summary>
|
||||
/// 远程项目的网络位置(WebSocket + IP + 端口 : 远程主机的文件路径)
|
||||
/// </summary>
|
||||
public string ProjectFileLocation { get; set; } = string.Empty;
|
||||
public bool IsGlobalInterrupt => false;
|
||||
|
||||
public bool IsControlRemoteEnv => true;
|
||||
|
||||
86
NodeFlow/Tool/AssemblyLoader.cs
Normal file
86
NodeFlow/Tool/AssemblyLoader.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Tool
|
||||
{
|
||||
/// <summary>
|
||||
/// 程序集加载器
|
||||
/// </summary>
|
||||
public class AssemblyLoader
|
||||
{
|
||||
private string _basePath;
|
||||
private AssemblyLoadContext context;
|
||||
private Dictionary<string, Type> dicTypes = new Dictionary<string, Type>();
|
||||
|
||||
public AssemblyLoader(string basePath)
|
||||
{
|
||||
_basePath = basePath;
|
||||
}
|
||||
|
||||
public Type Load(string dllFileName, string typeName)
|
||||
{
|
||||
context = new AssemblyLoadContext(dllFileName);
|
||||
context.Resolving += Context_Resolving;
|
||||
//需要绝对路径
|
||||
string path = Path.Combine(_basePath, dllFileName);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var stream = File.OpenRead(path))
|
||||
{
|
||||
Assembly assembly = context.LoadFromStream(stream);
|
||||
Type type = assembly.GetType(typeName);
|
||||
dicTypes.Add(typeName, type);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载节点{dllFileName}-{typeName}发生异常:{ex.Message},{ex.StackTrace}");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"节点动态库{dllFileName}不存在:{path}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载依赖文件
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="assemblyName"></param>
|
||||
/// <returns></returns>
|
||||
private Assembly Context_Resolving(AssemblyLoadContext context, AssemblyName assemblyName)
|
||||
{
|
||||
string expectedPath = Path.Combine(_basePath, assemblyName.Name + ".dll"); ;
|
||||
if (File.Exists(expectedPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var stream = File.OpenRead(expectedPath))
|
||||
{
|
||||
return context.LoadFromStream(stream);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载节点{expectedPath}发生异常:{ex.Message},{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"依赖文件不存在:{expectedPath}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,6 +220,10 @@ namespace Serein.NodeFlow.Tool
|
||||
var dir = Path.GetDirectoryName(dllFilePath); // 获取目录路径
|
||||
var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary);
|
||||
// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
||||
|
||||
//AssemblyLoader assemblyLoader = new AssemblyLoader(dllFilePath);
|
||||
|
||||
|
||||
var flowAlc = new FlowLibraryAssemblyContext(sereinFlowBaseLibraryPath, fileName);
|
||||
Action actionUnload = () =>
|
||||
{
|
||||
@@ -312,7 +316,7 @@ namespace Serein.NodeFlow.Tool
|
||||
/// <summary>
|
||||
/// 创建新的加载上下文
|
||||
/// </summary>
|
||||
/// <param name="sereinFlowLibraryPath">类库主</param>
|
||||
/// <param name="sereinFlowLibraryPath">类库路径</param>
|
||||
/// <param name="name"></param>
|
||||
public FlowLibraryAssemblyContext(string sereinFlowLibraryPath, string name) : base(name, isCollectible: true)
|
||||
{
|
||||
@@ -350,15 +354,15 @@ namespace Serein.NodeFlow.Tool
|
||||
//return null; // 如果没有找到,返回 null
|
||||
}
|
||||
}
|
||||
public static class PluginAssemblyContextExtensions
|
||||
{
|
||||
//public static class PluginAssemblyContextExtensions
|
||||
//{
|
||||
|
||||
public static Assembly FromAssemblyPath(this AssemblyLoadContext context, string path)
|
||||
{
|
||||
// public static Assembly FromAssemblyPath(this AssemblyLoadContext context, string path)
|
||||
// {
|
||||
|
||||
return context.LoadFromAssemblyPath(path);
|
||||
// return context.LoadFromAssemblyPath(path);
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -172,11 +172,12 @@ public static class NodeMethodDetailsHelper
|
||||
if (method == null) return string.Empty;
|
||||
|
||||
string methodName = method.Name;
|
||||
string returnType = method.ReturnType.Name;
|
||||
//string returnType = method.ReturnType.Name;
|
||||
string parameters = string.Join(", ", method.GetParameters()
|
||||
.Select(p => $"{p.ParameterType.Name} {p.Name}"));
|
||||
|
||||
return $"{methodName}({parameters}) : {returnType}";
|
||||
return $"{methodName}({parameters})";
|
||||
//return $"{methodName}({parameters}) : {returnType}";
|
||||
}
|
||||
public static bool IsGenericTask(Type returnType, out Type? taskResult)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user