diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs
index 41ef41e..78b9319 100644
--- a/Library/Api/IFlowEnvironment.cs
+++ b/Library/Api/IFlowEnvironment.cs
@@ -676,8 +676,8 @@ namespace Serein.Library.Api
///
/// 移除DLL
///
- /// 程序集的名称
- bool RemoteDll(string assemblyName);
+ /// 程序集的名称
+ bool RemoteDll(string assemblyFullName);
///
/// 清理加载的DLL(待更改)
@@ -860,7 +860,7 @@ namespace Serein.Library.Api
/// 方法描述
/// 方法信息
///
- bool TryGetMethodDetailsInfo(string methodName, out MethodDetailsInfo mdInfo);
+ bool TryGetMethodDetailsInfo(string libraryName, string methodName, out MethodDetailsInfo mdInfo);
///
/// 获取指定方法的Emit委托
@@ -868,7 +868,7 @@ namespace Serein.Library.Api
///
///
///
- bool TryGetDelegateDetails(string methodName, out DelegateDetails del);
+ bool TryGetDelegateDetails(string libraryName, string methodName, out DelegateDetails del);
#region 远程相关
diff --git a/Library/Entity/NodeLibraryInfo.cs b/Library/Entity/NodeLibraryInfo.cs
deleted file mode 100644
index 801dac8..0000000
--- a/Library/Entity/NodeLibraryInfo.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Reflection;
-using System.Text;
-
-namespace Serein.Library
-{
- ///
- /// 节点DLL依赖类,如果一个项目中引入了多个DLL,需要放置在同一个文件夹中
- ///
- public class NodeLibraryInfo
- {
- ///
- /// 文件名
- ///
- public string FileName { get; set; }
-
- ///
- /// 路径
- ///
- public string FilePath { get; set; }
-
- ///
- /// 所属的程序集名称
- ///
- public string AssemblyName{ get; set; }
- }
-
-
-
- ///
- ///
- ///
- public class FlowLibrary
- {
- public FlowLibrary(string assemblyName,
- Action actionOfUnloadAssmbly)
- {
- this.AssemblyName = assemblyName;
- this.actionOfUnloadAssmbly = actionOfUnloadAssmbly;
- }
-
- public string AssemblyName { get; }
-
- //public string AssemblyVersion { get; }
-
- ///
- /// 加载程序集时创建的方法描述
- ///
- public ConcurrentDictionary MethodDetailss { get; } = new ConcurrentDictionary();
-
- ///
- /// 管理通过Emit动态构建的委托
- ///
- public ConcurrentDictionary DelegateDetailss { get; } = new ConcurrentDictionary();
-
- ///
- /// 记录不同的注册时机需要自动创建全局唯一实例的类型信息
- ///
- public ConcurrentDictionary RegisterTypes { get; } = new ConcurrentDictionary();
-
-
- private readonly Action actionOfUnloadAssmbly;
-
- ///
- /// 卸载当前程序集以及附带的所有信息
- ///
- public void Upload()
- {
- actionOfUnloadAssmbly?.Invoke();
- }
-
-
- ///
- /// 通过方法名称获取对应的Emit委托(元数据),用于动态调用节点对应的方法
- ///
- /// 方法名称
- /// Emit委托
- ///
- public bool GetDelegateDetails(string methodName, out DelegateDetails dd)
- {
- return DelegateDetailss.TryGetValue(methodName, out dd);
- }
-
- ///
- /// 通过方法名称获取对应的方法描述(元数据),用于创建节点时,节点实例需要的方法描述
- ///
- /// 方法名称
- /// 方法描述
- ///
- public bool GetMethodDetails(string methodName, out MethodDetails md)
- {
- return MethodDetailss.TryGetValue(methodName, out md);
- }
-
- public NodeLibraryInfo ToInfo()
- {
- return new NodeLibraryInfo
- {
-
- }
- }
-
- }
-
-}
diff --git a/Library/FlowNode/MethodDetails.cs b/Library/FlowNode/MethodDetails.cs
index f9632bc..d8489e5 100644
--- a/Library/FlowNode/MethodDetails.cs
+++ b/Library/FlowNode/MethodDetails.cs
@@ -2,6 +2,7 @@
using Serein.Library.Utils;
using System;
using System.Linq;
+using System.Reflection;
using System.Text;
namespace Serein.Library
@@ -21,6 +22,13 @@ namespace Serein.Library
[PropertyInfo(IsProtection = true)]
private NodeModelBase _nodeModel;
+ ///
+ /// 对应的程序集
+ ///
+ [PropertyInfo]
+ private string _assemblyName;
+
+
///
/// 是否保护参数(目前仅视觉效果参数,不影响运行实现,后续将设置作用在运行逻辑中)
///
@@ -188,6 +196,7 @@ namespace Serein.Library
{
throw new ArgumentException("无效的节点类型");
}
+ AssemblyName = Info.AssemblyName;
MethodName = Info.MethodName;
MethodAnotherName = Info.MethodAnotherName;
MethodDynamicType = nodeType;
@@ -204,6 +213,7 @@ namespace Serein.Library
{
return new MethodDetailsInfo
{
+ AssemblyName = this.AssemblyName,
MethodName = this.MethodName,
MethodAnotherName = this.MethodAnotherName,
NodeType = this.MethodDynamicType.ToString(),
@@ -222,6 +232,7 @@ namespace Serein.Library
// this => 是元数据
var md = new MethodDetails( nodeModel) // 创建新节点时拷贝实例
{
+ AssemblyName = this.AssemblyName,
ActingInstance = this.ActingInstance,
ActingInstanceType = this.ActingInstanceType,
MethodDynamicType = this.MethodDynamicType,
@@ -231,8 +242,9 @@ namespace Serein.Library
MethodLockName = this.MethodLockName,
IsProtectionParameter = this.IsProtectionParameter,
ParamsArgIndex = this.ParamsArgIndex,
+ ParameterDetailss = this.ParameterDetailss?.Select(p => p?.CloneOfModel(nodeModel)).ToArray(), // 拷贝属于节点方法的新入参描述
};
- md.ParameterDetailss = this.ParameterDetailss?.Select(p => p?.CloneOfModel(nodeModel)).ToArray(); // 拷贝属于节点方法的新入参描述
+
return md;
}
diff --git a/Library/FlowNode/NodeModelBaseFunc.cs b/Library/FlowNode/NodeModelBaseFunc.cs
index 7422210..faec818 100644
--- a/Library/FlowNode/NodeModelBaseFunc.cs
+++ b/Library/FlowNode/NodeModelBaseFunc.cs
@@ -52,6 +52,7 @@ namespace Serein.Library
return new NodeInfo
{
Guid = Guid,
+ AssemblyName = MethodDetails.AssemblyName,
MethodName = MethodDetails?.MethodName,
Label = MethodDetails?.MethodAnotherName,
Type = this.GetType().ToString(),
@@ -316,7 +317,7 @@ namespace Serein.Library
{
throw new Exception($"节点{this.Guid}不存在方法信息,请检查是否需要重写节点的ExecutingAsync");
}
- if (!context.Env.TryGetDelegateDetails(md.MethodName, out var dd))
+ if (!context.Env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd))
{
throw new Exception($"节点{this.Guid}不存在对应委托");
}
diff --git a/Library/FlowNode/SereinProjectData.cs b/Library/FlowNode/SereinProjectData.cs
index cbc1813..a6cab50 100644
--- a/Library/FlowNode/SereinProjectData.cs
+++ b/Library/FlowNode/SereinProjectData.cs
@@ -61,7 +61,7 @@ namespace Serein.Library
/// 依赖的DLL
///
- public Library[] Librarys { get; set; }
+ public NodeLibraryInfo[] Librarys { get; set; }
///
/// 起始节点GUID
@@ -132,38 +132,63 @@ namespace Serein.Library
///
/// 项目依赖的程序集,项目文件相关
///
- public class Library
+ ///
+ public class NodeLibraryInfo
{
///
- /// 文件名称
+ /// 文件名
///
-
public string FileName { get; set; }
///
- /// 文件路径
+ /// 路径
///
public string FilePath { get; set; }
///
- /// 程序集名称
+ /// 所属的程序集名称
///
public string AssemblyName { get; set; }
}
+ #region 暂时注释
+ /*public class LibraryInfo
+{
+ ///
+ /// 文件名称
+ ///
+
+ public string FileName { get; set; }
+
+ ///
+ /// 文件路径
+ ///
+ public string FilePath { get; set; }
+
+ ///
+ /// 程序集名称
+ ///
+ public string AssemblyName { get; set; }
+}*/
+ #endregion
+
///
/// 节点信息,项目文件相关
///
public class NodeInfo
{
///
- /// GUID
+ /// 节点的GUID
///
-
public string Guid { get; set; }
///
- /// 名称
+ /// 节点方法所属的程序集名称
+ ///
+ public string AssemblyName { get;set; }
+
+ ///
+ /// 节点对应的名称
///
public string MethodName { get; set; }
diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs
index 15aa873..495494f 100644
--- a/NodeFlow/Env/FlowEnvironment.cs
+++ b/NodeFlow/Env/FlowEnvironment.cs
@@ -9,6 +9,7 @@ using Serein.Library.Utils.SereinExpression;
using Serein.NodeFlow.Model;
using Serein.NodeFlow.Tool;
using System.Collections.Concurrent;
+using System.Diagnostics;
using System.Numerics;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
@@ -52,7 +53,8 @@ namespace Serein.NodeFlow.Env
}
};
- this.UIContextOperation = uiContextOperation; // 本地环境需要存放视图管理
+ this.UIContextOperation = uiContextOperation; // 为加载的类库提供在UI线程上执行某些操作的封装工具类
+ this.FlowLibraryManagement = new FlowLibraryManagement(this); // 实例化类库管理
}
#region 远程管理
@@ -227,14 +229,16 @@ namespace Serein.NodeFlow.Env
///
/// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托
///
- public ConcurrentDictionary FlowLibrarys { get; } = [];
+ private readonly FlowLibraryManagement FlowLibraryManagement;
+#if false
///
/// Library 与 MethodDetailss的依赖关系
///
public ConcurrentDictionary> MethodDetailsOfLibraryInfos { get; } = [];
+
///
/// 存储已加载的程序集
/// Key:程序集的FullName
@@ -258,7 +262,8 @@ namespace Serein.NodeFlow.Env
/// 存放所有通过Emit加载的委托
/// md.Methodname - delegate
///
- private ConcurrentDictionary MethodDelegates { get; } = [];
+ private ConcurrentDictionary MethodDelegates { get; } = [];
+#endif
///
/// IOC对象容器管理
@@ -351,17 +356,13 @@ namespace Serein.NodeFlow.Env
flowStarter = new FlowStarter();
var nodes = NodeModels.Values.ToList();
- List initMethods = [];
- List loadMethods = [];
- List exitMethods = [];
+
- var initMds = MethodDetailss.Values.Where(it => it.MethodDynamicType == NodeType.Init);
- var loadMds = MethodDetailss.Values.Where(it => it.MethodDynamicType == NodeType.Loading);
- var exitMds = MethodDetailss.Values.Where(it => it.MethodDynamicType == NodeType.Exit);
+ List initMethods = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Init);
+ List loadMethods = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Loading);
+ List exitMethods = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Exit);
+ Dictionary> autoRegisterTypes = this.FlowLibraryManagement.GetaAutoRegisterType();
- initMethods.AddRange(initMds);
- loadMethods.AddRange(loadMds);
- exitMethods.AddRange(exitMds);
IOC.Reset(); // 开始运行时清空ioc中注册的实例
@@ -369,7 +370,7 @@ namespace Serein.NodeFlow.Env
if (this.UIContextOperation is not null)
IOC.CustomRegisterInstance(typeof(UIContextOperation).FullName, this.UIContextOperation, false);
- await flowStarter.RunAsync(this, nodes, AutoRegisterTypes, initMethods, loadMethods, exitMethods);
+ await flowStarter.RunAsync(this, nodes, autoRegisterTypes, initMethods, loadMethods, exitMethods);
if (FlipFlopState == RunState.Completion)
{
@@ -480,30 +481,9 @@ namespace Serein.NodeFlow.Env
///
public async Task GetEnvInfoAsync()
{
- Dictionary> MdsOfLibraryInfos = [];
-
- foreach (var mdskv in MethodDetailsOfLibraryInfos)
- {
- var library = mdskv.Key;
- var mds = mdskv.Value;
- foreach (var md in mds)
- {
- if (!MdsOfLibraryInfos.TryGetValue(library, out var t_mds))
- {
- t_mds = new List();
- MdsOfLibraryInfos[library] = t_mds;
- }
- var mdInfo = md.ToInfo();
- mdInfo.AssemblyName = library.AssemblyName;
- t_mds.Add(mdInfo);
- }
- }
-
- LibraryMds[] libraryMdss = MdsOfLibraryInfos.Select(kv => new LibraryMds
- {
- AssemblyName = kv.Key.AssemblyName,
- Mds = kv.Value.ToArray()
- }).ToArray();
+ // 获取所有的程序集对应的方法信息(程序集相关的数据)
+ var libraryMdss = this.FlowLibraryManagement.GetAllLibraryMds().ToArray();
+ // 获取当前项目的信息(节点相关的数据)
var project = await GetProjectInfoAsync();
Console.WriteLine("已将当前环境信息发送到远程客户端");
return new FlowEnvInfo
@@ -540,13 +520,13 @@ namespace Serein.NodeFlow.Env
foreach (var dllPath in dllPaths)
{
var dllFilePath = Path.GetFullPath(Path.Combine(filePath, dllPath));
- LoadDllNodeInfo(dllFilePath);
+ LoadDll(dllFilePath); // 加载项目文件时加载对应的程序集
}
List<(NodeModelBase, string[])> regionChildNodes = new List<(NodeModelBase, string[])>();
List<(NodeModelBase, PositionOfUI)> ordinaryNodes = new List<(NodeModelBase, PositionOfUI)>();
// 加载节点
- foreach (var nodeInfo in projectData.Nodes)
+ foreach (NodeInfo? nodeInfo in projectData.Nodes)
{
var controlType = FlowFunc.GetNodeControlType(nodeInfo);
if (controlType == NodeControlType.None)
@@ -555,11 +535,14 @@ namespace Serein.NodeFlow.Env
}
else
{
- MethodDetails? methodDetails = null;
- if (!string.IsNullOrEmpty(nodeInfo.MethodName))
+ if (string.IsNullOrEmpty(nodeInfo.AssemblyName) && string.IsNullOrEmpty(nodeInfo.MethodName))
{
- MethodDetailss.TryGetValue(nodeInfo.MethodName, out methodDetails);// 加载项目时尝试获取方法信息
+ continue;
}
+ MethodDetails? methodDetails = null;
+ FlowLibraryManagement.TryGetMethodDetails(nodeInfo.AssemblyName,
+ nodeInfo.MethodName,
+ out methodDetails); // 加载项目时尝试获取方法信息
var nodeModel = FlowFunc.CreateNode(this, controlType, methodDetails); // 加载项目时创建节点
nodeModel.LoadInfo(nodeInfo); // 创建节点model
if (nodeModel is null)
@@ -726,7 +709,7 @@ namespace Serein.NodeFlow.Env
{
var projectData = new SereinProjectData()
{
- Librarys = LibraryInfos.Values.Select(lib => lib.ToLibrary()).ToArray(),
+ Librarys = this.FlowLibraryManagement.GetAllLibraryInfo().ToArray(),
Nodes = NodeModels.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
};
@@ -739,10 +722,11 @@ namespace Serein.NodeFlow.Env
///
///
///
- // [AutoSocketHandle]
public void LoadDll(string dllPath)
{
- LoadDllNodeInfo(dllPath);
+ (var libraryInfo, var mdInfos) = FlowLibraryManagement.LoadLibrary(dllPath);
+ UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示
+
}
///
@@ -752,49 +736,51 @@ namespace Serein.NodeFlow.Env
///
public bool RemoteDll(string assemblyName)
{
- var library = LibraryInfos.Values.FirstOrDefault(nl => assemblyName.Equals(nl.AssemblyName));
- if (library is null)
- {
- return false;
- }
- var groupedNodes = NodeModels.Values
- .Where(node => node.MethodDetails is not null)
- .ToArray()
- .GroupBy(node => node.MethodDetails?.MethodName)
- .ToDictionary(
- key => key.Key,
- group => group.Count());
+ return FlowLibraryManagement.UnloadLibrary(assemblyName);
+
+ //var library = LibraryInfos.Values.FirstOrDefault(nl => assemblyName.Equals(nl.AssemblyName));
+ //if (library is null)
+ //{
+ // return false;
+ //}
+ //var groupedNodes = NodeModels.Values
+ // .Where(node => node.MethodDetails is not null)
+ // .ToArray()
+ // .GroupBy(node => node.MethodDetails?.MethodName)
+ // .ToDictionary(
+ // key => key.Key,
+ // group => group.Count());
- if (NodeModels.Count == 0)
- {
- return true; // 当前无节点,可以直接删除
- }
+ //if (NodeModels.Count == 0)
+ //{
+ // return true; // 当前无节点,可以直接删除
+ //}
- if (MethodDetailsOfLibraryInfos.TryGetValue(library, out var mds)) // 存在方法
- {
- foreach (var md in mds)
- {
- if (groupedNodes.TryGetValue(md.MethodName, out int count))
- {
- if (count > 0)
- {
- return false; // 创建过相关的节点,无法移除
- }
- }
- }
- // 开始移除相关信息
- foreach (var md in mds)
- {
- MethodDetailss.TryRemove(md.MethodName, out _);
- }
- MethodDetailsOfLibraryInfos.TryRemove(library, out _);
- return true;
- }
- else
- {
- return true;
- }
+ //if (MethodDetailsOfLibraryInfos.TryGetValue(library, out var mds)) // 存在方法
+ //{
+ // foreach (var md in mds)
+ // {
+ // if (groupedNodes.TryGetValue(md.MethodName, out int count))
+ // {
+ // if (count > 0)
+ // {
+ // return false; // 创建过相关的节点,无法移除
+ // }
+ // }
+ // }
+ // // 开始移除相关信息
+ // foreach (var md in mds)
+ // {
+ // MethodDetailss.TryRemove(md.MethodName, out _);
+ // }
+ // MethodDetailsOfLibraryInfos.TryRemove(library, out _);
+ // return true;
+ //}
+ //else
+ //{
+ // return true;
+ //}
}
@@ -814,7 +800,9 @@ namespace Serein.NodeFlow.Env
}
else
{
- if (MethodDetailss.TryGetValue(methodDetailsInfo.MethodName, out var methodDetails))
+ if (FlowLibraryManagement.TryGetMethodDetails(methodDetailsInfo.AssemblyName,
+ methodDetailsInfo.MethodName,
+ out var methodDetails))
{
nodeModel = FlowFunc.CreateNode(this, nodeControlType, methodDetails); // 一般的加载节点方法
}
@@ -1026,25 +1014,18 @@ namespace Serein.NodeFlow.Env
/// 获取方法描述
///
- public bool TryGetMethodDetailsInfo(string name, out MethodDetailsInfo? md)
+ public bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo? mdInfo)
{
- if (!string.IsNullOrEmpty(name))
+ var isPass = FlowLibraryManagement.TryGetMethodDetails(assemblyName, methodName, out var md);
+ if (!isPass || md is null)
{
- foreach (var t_md in MethodDetailss.Values)
- {
- md = t_md.ToInfo();
- if (md != null)
- {
- return true;
- }
- }
- md = null;
+ mdInfo = null;
return false;
}
else
{
- md = null;
- return false;
+ mdInfo = md?.ToInfo();
+ return true;
}
}
@@ -1058,18 +1039,9 @@ namespace Serein.NodeFlow.Env
///
///
///
- public bool TryGetDelegateDetails(string methodName, out DelegateDetails? delegateDetails)
+ public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails? delegateDetails)
{
-
- if (!string.IsNullOrEmpty(methodName) && MethodDelegates.TryGetValue(methodName, out delegateDetails))
- {
- return delegateDetails != null;
- }
- else
- {
- delegateDetails = null;
- return false;
- }
+ return FlowLibraryManagement.TryGetDelegateDetails(assemblyName, methodName, out delegateDetails);
}
@@ -1399,6 +1371,8 @@ namespace Serein.NodeFlow.Env
#region 私有方法
+ #region 暂时注释
+ /*
///
/// 加载指定路径的DLL文件
///
@@ -1455,7 +1429,8 @@ namespace Serein.NodeFlow.Env
- }
+ }*/
+ #endregion
///
/// 移除连接关系
@@ -1507,7 +1482,8 @@ namespace Serein.NodeFlow.Env
return true;
}
- ///
+ #region 暂时注释
+ /*///
/// 动态加载程序集
///
/// 程序集本身
@@ -1597,7 +1573,8 @@ namespace Serein.NodeFlow.Env
Console.WriteLine(ex.ToString());
return ([], []);
}
- }
+ }*/
+ #endregion
///
/// 创建节点
diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs
index c46f69b..ff5c22d 100644
--- a/NodeFlow/Env/FlowEnvironmentDecorator.cs
+++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs
@@ -390,14 +390,14 @@ namespace Serein.NodeFlow.Env
currentFlowEnvironment.TriggerInterrupt(nodeGuid, expression, type);
}
- public bool TryGetDelegateDetails(string methodName, out DelegateDetails del)
+ public bool TryGetDelegateDetails(string libraryName, string methodName, out DelegateDetails del)
{
- return currentFlowEnvironment.TryGetDelegateDetails(methodName, out del);
+ return currentFlowEnvironment.TryGetDelegateDetails(libraryName, methodName, out del);
}
- public bool TryGetMethodDetailsInfo(string methodName, out MethodDetailsInfo mdInfo)
+ public bool TryGetMethodDetailsInfo(string libraryName, string methodName, out MethodDetailsInfo mdInfo)
{
- return currentFlowEnvironment.TryGetMethodDetailsInfo(methodName, out mdInfo);
+ return currentFlowEnvironment.TryGetMethodDetailsInfo(libraryName, methodName, out mdInfo);
}
public void WriteLineObjToJson(object obj)
diff --git a/NodeFlow/Env/FlowFunc.cs b/NodeFlow/Env/FlowFunc.cs
index 687ebc5..e7ec836 100644
--- a/NodeFlow/Env/FlowFunc.cs
+++ b/NodeFlow/Env/FlowFunc.cs
@@ -89,13 +89,11 @@ namespace Serein.NodeFlow.Env
///
///
///
- public static Library.Library ToLibrary(this Library.NodeLibraryInfo libraryInfo)
+ public static NodeLibraryInfo ToLibrary(this Library.NodeLibraryInfo libraryInfo)
{
- //var tmp = library.Assembly.ManifestModule.Name;
- return new Library.Library
+ return new NodeLibraryInfo
{
AssemblyName = libraryInfo.AssemblyName,
- //AssemblyName = library.Assembly.GetName().Name,
FileName = libraryInfo.FileName,
FilePath = libraryInfo.FilePath,
};
diff --git a/NodeFlow/Env/RemoteFlowEnvironment.cs b/NodeFlow/Env/RemoteFlowEnvironment.cs
index 82c4746..393c31f 100644
--- a/NodeFlow/Env/RemoteFlowEnvironment.cs
+++ b/NodeFlow/Env/RemoteFlowEnvironment.cs
@@ -129,6 +129,7 @@ namespace Serein.NodeFlow.Env
{
AssemblyName = lib.AssemblyName,
FilePath = "Remote",
+ FileName = "Remote",
};
var mdInfos = lib.Mds.ToList();
UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibraryInfo, mdInfos))); // 通知UI创建dll面板显示
@@ -791,14 +792,14 @@ namespace Serein.NodeFlow.Env
return ChannelFlowInterrupt.CancelType.Error;
}
- public bool TryGetMethodDetailsInfo(string methodName, out MethodDetailsInfo mdInfo)
+ public bool TryGetMethodDetailsInfo(string libraryName, string methodName, out MethodDetailsInfo mdInfo)
{
Console.WriteLine("远程环境尚未实现的接口:TryGetMethodDetailsInfo");
mdInfo = null;
return false;
}
- public bool TryGetDelegateDetails(string methodName, out DelegateDetails del)
+ public bool TryGetDelegateDetails(string libraryName, string methodName, out DelegateDetails del)
{
Console.WriteLine("远程环境尚未实现的接口:TryGetDelegateDetails");
del = null;
diff --git a/NodeFlow/FlowStarter.cs b/NodeFlow/FlowStarter.cs
index 961b110..96474b0 100644
--- a/NodeFlow/FlowStarter.cs
+++ b/NodeFlow/FlowStarter.cs
@@ -184,7 +184,7 @@ namespace Serein.NodeFlow
//object?[]? args = [Context];
foreach (var md in initMethods) // 初始化
{
- if (!env.TryGetDelegateDetails(md.MethodName, out var dd))
+ if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd))
{
throw new Exception("不存在对应委托");
}
@@ -205,7 +205,7 @@ namespace Serein.NodeFlow
{
//object?[]? data = [md.ActingInstance, args];
//md.MethodDelegate.DynamicInvoke(data);
- if (!env.TryGetDelegateDetails(md.MethodName, out var dd))
+ if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd))
{
throw new Exception("不存在对应委托");
}
@@ -228,7 +228,7 @@ namespace Serein.NodeFlow
foreach (MethodDetails? md in exitMethods)
{
- if (!env.TryGetDelegateDetails(md.MethodName, out var dd))
+ if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd))
{
throw new Exception("不存在对应委托");
}
diff --git a/NodeFlow/Model/CompositeConditionNode.cs b/NodeFlow/Model/CompositeConditionNode.cs
index 316fe12..788067b 100644
--- a/NodeFlow/Model/CompositeConditionNode.cs
+++ b/NodeFlow/Model/CompositeConditionNode.cs
@@ -111,7 +111,8 @@ namespace Serein.NodeFlow.Model
return new NodeInfo
{
Guid = Guid,
- MethodName = MethodDetails?.MethodName,
+ AssemblyName = MethodDetails.AssemblyName,
+ MethodName = MethodDetails.MethodName,
Label = MethodDetails?.MethodAnotherName,
Type = this.GetType().ToString(),
TrueNodes = trueNodes.ToArray(),
diff --git a/NodeFlow/Model/SingleFlipflopNode.cs b/NodeFlow/Model/SingleFlipflopNode.cs
index f6b99fe..b213c75 100644
--- a/NodeFlow/Model/SingleFlipflopNode.cs
+++ b/NodeFlow/Model/SingleFlipflopNode.cs
@@ -43,7 +43,7 @@ namespace Serein.NodeFlow.Model
#endregion
MethodDetails md = MethodDetails;
- if (!context.Env.TryGetDelegateDetails(md.MethodName, out var dd))
+ if (!context.Env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd))
{
throw new Exception("不存在对应委托");
}
diff --git a/NodeFlow/Tool/FlowLibrary.cs b/NodeFlow/Tool/FlowLibrary.cs
new file mode 100644
index 0000000..4754353
--- /dev/null
+++ b/NodeFlow/Tool/FlowLibrary.cs
@@ -0,0 +1,230 @@
+using Serein.Library;
+using Serein.NodeFlow.Tool;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace Serein.NodeFlow
+{
+
+ ///
+ ///
+ ///
+ public class FlowLibrary
+ {
+ private readonly Assembly assembly;
+ private readonly Action actionOfUnloadAssmbly;
+ private string _assemblyFilePath;
+
+ public FlowLibrary(string assemblyFilePath,
+ Assembly assembly,
+ Action actionOfUnloadAssmbly)
+ {
+ this._assemblyFilePath = assemblyFilePath;
+ this.assembly = assembly;
+ this.actionOfUnloadAssmbly = actionOfUnloadAssmbly;
+ LoadAssembly(assembly);
+ }
+
+
+ public string FullName => assembly.GetName().FullName;
+
+ public string Version => assembly.GetName().Version.ToString();
+
+ ///
+ /// 加载程序集时创建的方法描述
+ ///
+ public ConcurrentDictionary MethodDetailss { get; } = new ConcurrentDictionary();
+
+ ///
+ /// 管理通过Emit动态构建的委托
+ ///
+ public ConcurrentDictionary DelegateDetailss { get; } = new ConcurrentDictionary();
+
+ ///
+ /// 记录不同的注册时机需要自动创建全局唯一实例的类型信息
+ ///
+ public ConcurrentDictionary> RegisterTypes { get; } = new ConcurrentDictionary>();
+
+
+ ///
+ /// 卸载当前程序集以及附带的所有信息
+ ///
+ public void Upload()
+ {
+ actionOfUnloadAssmbly?.Invoke();
+ }
+
+ public NodeLibraryInfo ToInfo()
+ {
+ return new NodeLibraryInfo
+ {
+ AssemblyName = FullName,
+ FileName = Path.GetFileName(_assemblyFilePath),
+ FilePath = _assemblyFilePath,
+ };
+ }
+
+
+ //public void LoadAssmely(Assembly assembly)
+ //{
+ // (var registerTypes, var mdlist) = LoadAssembly2(assembly);
+ // if (mdlist.Count > 0)
+ // {
+ // var nodeLibraryInfo = new NodeLibraryInfo
+ // {
+ // //Assembly = assembly,
+ // AssemblyName = assembly.FullName,
+ // FileName = Path.GetFileName(_assemblyFilePath),
+ // FilePath = _assemblyFilePath,
+ // };
+
+ // //LibraryInfos.TryAdd(nodeLibraryInfo.AssemblyName, nodeLibraryInfo);
+
+ // MethodDetailss.TryAdd(nodeLibraryInfo.AssemblyName, mdlist);
+
+ // foreach (var md in mdlist)
+ // {
+ // MethodDetailss.TryAdd(md.MethodName, md);
+ // }
+
+ // foreach (var kv in registerTypes)
+ // {
+ // if (!RegisterTypes.TryGetValue(kv.Key, out var types))
+ // {
+ // types = new List();
+ // RegisterTypes.TryAdd(kv.Key, types);
+ // }
+ // types.AddRange(kv.Value);
+ // }
+ // var mdInfos = mdlist.Select(md => md.ToInfo()).ToList(); // 转换成方法信息
+ // }
+ //}
+
+
+ ///
+ /// 动态加载程序集
+ ///
+ /// 程序集本身
+ ///
+ private bool LoadAssembly(Assembly assembly)
+ {
+ #region 检查入参
+
+ // 加载DLL,创建 MethodDetails、实例作用对象、委托方法
+ var assemblyName = assembly.GetName().Name;
+ if (string.IsNullOrEmpty(assemblyName)) // 防止动态程序集没有定义程序集名称
+ {
+ return false;
+ }
+
+ List types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型
+ if (types.Count < 0) // 防止动态程序集中没有类型信息?
+ {
+ return false;
+ }
+
+ #endregion
+
+
+ try
+ {
+
+
+ #region 获取 DynamicFlow 特性的流程控制器,如果没有退出
+ // Type : 具有 DynamicFlowAttribute 标记的类型
+ // string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性 (用于生成方法描述时,添加在方法别名中提高可读性)
+ List<(Type Type, string Name)> scanTypes = new List<(Type Type, string Name)>();
+
+ // (Type, string)
+ // Type : 具有 DynamicFlowAttribute 标记的类型
+ // string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性
+ foreach (var type in types)
+ {
+ if (type.GetCustomAttribute() is DynamicFlowAttribute dynamicFlowAttribute && dynamicFlowAttribute.Scan == true)
+ {
+ scanTypes.Add((type, dynamicFlowAttribute.Name));
+ }
+ }
+ if (scanTypes.Count == 0)
+ {
+ // 类型没有流程控制器
+ return false;
+ }
+ #endregion
+
+
+ #region 创建对应的方法元数据
+ // 从 scanTypes.Type 创建的方法信息
+ // Md : 方法描述
+ // Dd :方法对应的Emit委托
+ List<(MethodDetails Md, DelegateDetails Dd)> detailss = new List<(MethodDetails Md, DelegateDetails Dd)>();
+
+ // 遍历扫描的类型
+ foreach ((var type, var flowName) in scanTypes)
+ {
+ var methodInfos = NodeMethodDetailsHelper.GetMethodsToProcess(type);
+ foreach (var methodInfo in methodInfos) // 遍历流程控制器类型中的方法信息
+ {
+ // 尝试创建
+ if (!NodeMethodDetailsHelper.TryCreateDetails(type, methodInfo, assemblyName,
+ out var md, out var dd)) // 返回的描述
+ {
+ Console.WriteLine($"无法加载方法信息:{assemblyName}-{type}-{methodInfo}");
+ continue;
+ }
+ md.MethodAnotherName = flowName + md.MethodAnotherName; // 方法别名
+ detailss.Add((md, dd));
+ }
+ }
+
+ #endregion
+
+ #region 检查是否成功加载,如果成功,则真正写入到缓存的集合中
+ if(detailss.Count == 0)
+ {
+ return false;
+ }
+ #region 加载成功,缓存所有方法、委托的信息
+ foreach((var md,var dd) in detailss)
+ {
+ MethodDetailss.TryAdd(md.MethodName, md);
+ DelegateDetailss.TryAdd(md.MethodName, dd);
+ }
+
+ #endregion
+ #region 加载成功,开始获取并记录所有需要自动实例化的类型(在流程启动时)
+ foreach (Type type in types)
+ {
+ if (type.GetCustomAttribute() is AutoRegisterAttribute attribute)
+ {
+ if (!RegisterTypes.TryGetValue(attribute.Class, out var valus))
+ {
+ valus = new List();
+ RegisterTypes.TryAdd(attribute.Class, valus);
+ }
+ valus.Add(type);
+ }
+ }
+ #endregion
+
+ #endregion
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.ToString());
+ return false;
+ }
+ }
+
+
+ }
+
+}
diff --git a/NodeFlow/Tool/FlowLibraryLoader.cs b/NodeFlow/Tool/FlowLibraryLoader.cs
deleted file mode 100644
index e1e2115..0000000
--- a/NodeFlow/Tool/FlowLibraryLoader.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-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
-{
- ///
- /// 管理加载在流程的程序集
- ///
- public class FlowLibraryLoader : AssemblyLoadContext
- {
- private Assembly _pluginAssembly;
-
- public string FullName => _pluginAssembly.FullName;
-
- ///
- /// 加载程序集
- ///
- ///
- public FlowLibraryLoader(string pluginPath) : base(isCollectible: true)
- {
- _pluginAssembly = LoadFromAssemblyPath(pluginPath);
- }
-
- ///
- /// 保持默认加载行为
- ///
- ///
- ///
-
- protected override Assembly Load(AssemblyName assemblyName)
- {
- return null; // 保持默认加载行为
- }
-
-
- public List LoadFlowTypes()
- {
- return _pluginAssembly.GetTypes().ToList();
- }
-
- ///
- /// 是否对程序集的引用
- ///
- public void UnloadPlugin()
- {
- _pluginAssembly = null; // 释放对程序集的引用
- Unload(); // 触发卸载
- // 强制进行垃圾回收,以便完成卸载
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
- }
-
-
-
-}
diff --git a/NodeFlow/Tool/FlowLibraryManagement.cs b/NodeFlow/Tool/FlowLibraryManagement.cs
new file mode 100644
index 0000000..aeddad1
--- /dev/null
+++ b/NodeFlow/Tool/FlowLibraryManagement.cs
@@ -0,0 +1,264 @@
+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();
+ //}
+ }
+
+
+
+}
diff --git a/NodeFlow/Tool/NodeMethodDetailsHelper.cs b/NodeFlow/Tool/NodeMethodDetailsHelper.cs
index 9e88725..45edc57 100644
--- a/NodeFlow/Tool/NodeMethodDetailsHelper.cs
+++ b/NodeFlow/Tool/NodeMethodDetailsHelper.cs
@@ -5,6 +5,7 @@ using System.Collections.Concurrent;
using System.Reflection;
using Serein.Library.FlowNode;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace Serein.NodeFlow.Tool;
@@ -21,21 +22,35 @@ public static class NodeMethodDetailsHelper
}
///
- /// 创建方法信息
+ /// 创建方法信息/委托信息
///
- ///
- public static (MethodDetails?, DelegateDetails?) CreateMethodDetails(Type type, MethodInfo method, string assemblyName)
+ /// 方法所属的类型
+ /// 方法信息
+ /// 方法所属的程序集名称
+ /// 创建的方法描述,用来生成节点信息
+ /// 方法对应的Emit动态委托
+ /// 指示是否创建成功
+ public static bool TryCreateDetails(Type type,
+ MethodInfo methodInfo,
+ string assemblyName,
+ [MaybeNullWhen(false)] out MethodDetails methodDetails,
+ [MaybeNullWhen(false)] out DelegateDetails delegateDetails)
{
- var attribute = method.GetCustomAttribute();
+
+
+ var attribute = methodInfo.GetCustomAttribute();
if(attribute is null || attribute.Scan == false)
{
- return (null, null);
+ methodDetails = null;
+ delegateDetails = null;
+ return false;
}
- //var dllTypeName = $"{assemblyName}.{type.Name}";
- var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}";
- Console.WriteLine("loading method : " +dllTypeMethodName);
- Debug.WriteLine("loading method : " +dllTypeMethodName);
- var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters());
+
+ var methodName = $"{assemblyName}.{type.Name}.{methodInfo.Name}";
+ Console.WriteLine("loading method : " + methodName);
+
+ // 创建参数信息
+ var explicitDataOfParameters = GetExplicitDataOfParameters(methodInfo.GetParameters());
@@ -46,17 +61,17 @@ public static class NodeMethodDetailsHelper
// method.ReturnType);// 返回值
//// 通过表达式树生成委托
- var emitMethodType = EmitHelper.CreateDynamicMethod(method, out var methodDelegate);// 返回值
+ var emitMethodType = EmitHelper.CreateDynamicMethod(methodInfo, out var methodDelegate);// 返回值
Type? returnType;
- bool isTask = IsGenericTask(method.ReturnType, out var taskResult);
+ bool isTask = IsGenericTask(methodInfo.ReturnType, out var taskResult);
if (attribute.MethodDynamicType == Library.NodeType.Flipflop)
{
- if (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
+ if (methodInfo.ReturnType.IsGenericType && methodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
{
// 获取 Task<> 的泛型参数类型
- var innerType = method.ReturnType.GetGenericArguments()[0];
+ var innerType = methodInfo.ReturnType.GetGenericArguments()[0];
if (innerType.IsGenericType && innerType.GetGenericTypeDefinition() == typeof(IFlipflopContext<>))
{
var flipflopType = innerType.GetGenericArguments()[0];
@@ -64,14 +79,18 @@ public static class NodeMethodDetailsHelper
}
else
{
- Console.WriteLine($"[{dllTypeMethodName}]跳过创建,返回类型非预期的Task>。");
- return (null, null);
+ Console.WriteLine($"[{methodName}]跳过创建,返回类型非预期的Task>。");
+ methodDetails = null;
+ delegateDetails = null;
+ return false;
}
}
else
{
- Console.WriteLine($"[{dllTypeMethodName}]跳过创建,因为触发器方法的返回值并非Task<>,将无法等待。");
- return (null, null);
+ Console.WriteLine($"[{methodName}]跳过创建,因为触发器方法的返回值并非Task<>,将无法等待。");
+ methodDetails = null;
+ delegateDetails = null;
+ return false;
}
//if (!isTask || taskResult != typeof(IFlipflopContext