From aa3d1763edf1a45de852151f3d7dd188d92af7e0 Mon Sep 17 00:00:00 2001
From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com>
Date: Tue, 8 Jul 2025 17:37:03 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86=E8=8A=82=E7=82=B9?=
=?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Library/Enums/ConnectionInvokeType.cs | 10 +-
Library/Extension/FlowModelExtension.cs | 19 ++-
.../FlowNode/LightweightFlowEnvironment.cs | 63 +++++--
Library/FlowNode/SereinProjectData.cs | 12 +-
Library/Utils/BenchmarkHelpers.cs | 3 +-
NodeFlow/Env/FlowEdit.cs | 85 ++++++++--
NodeFlow/Services/FlowCoreGenerateService.cs | 160 +++++++++++-------
.../Converters/BoolToVisibilityConverter.cs | 2 +-
8 files changed, 260 insertions(+), 94 deletions(-)
diff --git a/Library/Enums/ConnectionInvokeType.cs b/Library/Enums/ConnectionInvokeType.cs
index 9164d57..ef91b69 100644
--- a/Library/Enums/ConnectionInvokeType.cs
+++ b/Library/Enums/ConnectionInvokeType.cs
@@ -13,23 +13,23 @@ namespace Serein.Library
///
/// 将不会继续执行
///
- None,
+ None = -1,
///
/// 上游分支(执行当前节点前会执行一次上游分支),默认执行。
///
- Upstream,
+ Upstream = 0,
///
/// 真分支(表示当前节点顺利完成)
///
- IsSucceed,
+ IsSucceed = 1,
///
/// 假分支(一般用于条件控件,条件为假时才会触发该类型的分支)
///
- IsFail,
+ IsFail = 2,
///
/// 异常发生分支(当前节点对应的方法执行时出现非预期的异常)
///
- IsError,
+ IsError = 3,
}
diff --git a/Library/Extension/FlowModelExtension.cs b/Library/Extension/FlowModelExtension.cs
index a3890c9..5b02b24 100644
--- a/Library/Extension/FlowModelExtension.cs
+++ b/Library/Extension/FlowModelExtension.cs
@@ -96,12 +96,17 @@ namespace Serein.Library
public static NodeInfo ToInfo(this IFlowNode nodeModel)
{
// if (MethodDetails == null) return null;
- var trueNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsSucceed].Select(item => item.Guid); // 真分支
+ /*var trueNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsSucceed].Select(item => item.Guid); // 真分支
var falseNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsFail].Select(item => item.Guid);// 假分支
var errorNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsError].Select(item => item.Guid);// 异常分支
- var upstreamNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.Upstream].Select(item => item.Guid);// 上游分支
+ var upstreamNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.Upstream].Select(item => item.Guid);// 上游分支*/
+
+ var successorNodes = nodeModel.SuccessorNodes.ToDictionary(kv => kv.Key, kv => kv.Value.Select(item => item.Guid).ToArray()); // 后继分支
+ var previousNodes = nodeModel.PreviousNodes.ToDictionary(kv => kv.Key, kv => kv.Value.Select(item => item.Guid).ToArray()); // 后继分支
+
+
// 生成参数列表
- ParameterData[] parameterData = nodeModel.SaveParameterInfo();
+ ParameterData[] parameterDatas = nodeModel.SaveParameterInfo();
var nodeInfo = new NodeInfo
{
@@ -112,17 +117,19 @@ namespace Serein.Library
MethodName = nodeModel.MethodDetails?.MethodName,
Label = nodeModel.MethodDetails?.MethodAnotherName,
Type = nodeModel.ControlType.ToString(), //this.GetType().ToString(),
- TrueNodes = trueNodes.ToArray(),
+ /*TrueNodes = trueNodes.ToArray(),
FalseNodes = falseNodes.ToArray(),
UpstreamNodes = upstreamNodes.ToArray(),
- ParameterData = parameterData.ToArray(),
- ErrorNodes = errorNodes.ToArray(),
+ ErrorNodes = errorNodes.ToArray(),*/
+ ParameterData = parameterDatas,
Position = nodeModel.Position,
IsProtectionParameter = nodeModel.DebugSetting.IsProtectionParameter,
IsInterrupt = nodeModel.DebugSetting.IsInterrupt,
IsEnable = nodeModel.DebugSetting.IsEnable,
ParentNodeGuid = nodeModel.ContainerNode?.Guid,
ChildNodeGuids = nodeModel.ChildrenNode.Select(item => item.Guid).ToArray(),
+ SuccessorNodes = successorNodes,
+ PreviousNodes = previousNodes,
};
nodeInfo.Position.X = Math.Round(nodeInfo.Position.X, 1);
nodeInfo.Position.Y = Math.Round(nodeInfo.Position.Y, 1);
diff --git a/Library/FlowNode/LightweightFlowEnvironment.cs b/Library/FlowNode/LightweightFlowEnvironment.cs
index 95557e5..40644f7 100644
--- a/Library/FlowNode/LightweightFlowEnvironment.cs
+++ b/Library/FlowNode/LightweightFlowEnvironment.cs
@@ -148,11 +148,11 @@ namespace Serein.Library
private void Init()
{
- PreviousNodes = new Dictionary>();
+ //PreviousNodes = new Dictionary>();
SuccessorNodes = new Dictionary>();
foreach (ConnectionInvokeType ctType in NodeStaticConfig.ConnectionTypes)
{
- PreviousNodes[ctType] = new List();
+ //PreviousNodes[ctType] = new List();
SuccessorNodes[ctType] = new List();
}
}
@@ -175,23 +175,48 @@ namespace Serein.Library
///
/// 不同分支的父节点(流程调用)
///
- public Dictionary> PreviousNodes { get; private set; }
+ //public Dictionary> PreviousNodes { get; private set; }
///
/// 不同分支的子节点(流程调用)
///
- public Dictionary> SuccessorNodes { get; private set; }
+ public Dictionary> SuccessorNodes { get; private set; }
+ public CallNode[][] ChildNodes { get; private set; } = new CallNode[][]
+ {
+ new CallNode[32],
+ new CallNode[32],
+ new CallNode[32],
+ new CallNode[32]
+ };
+ public int GetCount(ConnectionInvokeType type)
+ {
+ if (type == ConnectionInvokeType.Upstream) return UpstreamNodeCount;
+ if (type == ConnectionInvokeType.IsSucceed) return IsSuccessorNodeCount;
+ if (type == ConnectionInvokeType.IsFail) return IsFailNodeCount;
+ if (type == ConnectionInvokeType.IsError) return IsErrorNodeCount;
+ return 0;
+ }
+
+ public int UpstreamNodeCount { get; private set; } = 0;
+ public int IsSuccessorNodeCount { get; private set; } = 0;
+ public int IsFailNodeCount { get; private set; } = 0;
+ public int IsErrorNodeCount { get; private set; } = 0;
public CallNode AddChildNodeUpstream(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.Upstream;
+ ChildNodes[(int)connectionInvokeType][UpstreamNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
}
+
public CallNode AddChildNodeSucceed(CallNode callNode)
{
- var connectionInvokeType = ConnectionInvokeType.IsSucceed;
+ ChildNodes[0][UpstreamNodeCount++] = callNode;
+
+ var connectionInvokeType = ConnectionInvokeType.IsSucceed;
+ ChildNodes[(int)connectionInvokeType][IsSuccessorNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
@@ -199,6 +224,7 @@ namespace Serein.Library
public CallNode AddChildNodeFail(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.IsFail;
+ ChildNodes[(int)connectionInvokeType][IsFailNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
@@ -206,6 +232,7 @@ namespace Serein.Library
public CallNode AddChildNodeError(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.IsError;
+ ChildNodes[(int)connectionInvokeType][IsErrorNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
}
@@ -240,7 +267,6 @@ namespace Serein.Library
private static readonly DefaultObjectPool> _stackPool = new DefaultObjectPool>(new DefaultPooledObjectPolicy>());
-
///
/// 开始执行
@@ -282,7 +308,6 @@ namespace Serein.Library
#endregion
#region 执行完成时更新栈
-
// 首先将指定类别后继分支的所有节点逆序推入栈中
var nextNodes = currentNode.SuccessorNodes[context.NextOrientation];
for (int index = nextNodes.Count - 1; index >= 0; index--)
@@ -345,11 +370,16 @@ namespace Serein.Library
{
private readonly IFlowCallTree flowCallTree;
private readonly IFlowEnvironment flowEnvironment;
+ public static Serein.Library.Utils.ObjectPool FlowContextPool { get; set; }
public LightweightFlowControl(IFlowCallTree flowCallTree, IFlowEnvironment flowEnvironment)
{
this.flowCallTree = flowCallTree;
this.flowEnvironment = flowEnvironment;
+ FlowContextPool = new Utils.ObjectPool(() =>
+ {
+ return new DynamicContext(flowEnvironment);
+ });
}
public Task
public string Type { get; set; }
+ ///
+ /// 父节点集合
+ ///
+ public Dictionary PreviousNodes { get; set; }
+
+ ///
+ /// 后续节点集合
+ ///
+ public Dictionary SuccessorNodes { get; set; }
+
///
/// 真分支节点GUID
///
@@ -189,7 +199,7 @@ namespace Serein.Library
///
- /// 父级节点Guid
+ /// 如果节点放置在了区域控件上,这里会有父级节点Guid
///
public string ParentNodeGuid{ get; set; }
diff --git a/Library/Utils/BenchmarkHelpers.cs b/Library/Utils/BenchmarkHelpers.cs
index 99eb65e..46b207d 100644
--- a/Library/Utils/BenchmarkHelpers.cs
+++ b/Library/Utils/BenchmarkHelpers.cs
@@ -15,7 +15,7 @@ namespace Serein.Library.Utils
///
/// 运行指定异步方法多次并输出耗时的最大、最小和平均值。
///
- /// 需要执行的异步方法
+ /// 需要执行的方法
/// 执行次数,默认10000
public static void Benchmark(Action action, int count = 10000)
{
@@ -38,6 +38,7 @@ namespace Serein.Library.Utils
double avg = total / count;
Console.WriteLine($"运行 {count} 次:");
+ Console.WriteLine($"总耗时 :{total} 毫秒:");
Console.WriteLine($"最大耗时:{max} 毫秒");
Console.WriteLine($"最小耗时:{min} 毫秒");
Console.WriteLine($"平均耗时:{avg} 毫秒");
diff --git a/NodeFlow/Env/FlowEdit.cs b/NodeFlow/Env/FlowEdit.cs
index a809a04..a090bfe 100644
--- a/NodeFlow/Env/FlowEdit.cs
+++ b/NodeFlow/Env/FlowEdit.cs
@@ -504,6 +504,7 @@ namespace Serein.NodeFlow.Env
#endregion
await Task.Delay(100);
+
#region 确定节点之间的方法调用关系
foreach (var nodeInfo in nodeInfos)
{
@@ -513,14 +514,13 @@ namespace Serein.NodeFlow.Env
return;
}
if (fromNodeModel is null) continue;
- List<(ConnectionInvokeType connectionType, string[] guids)> allToNodes = [(ConnectionInvokeType.IsSucceed,nodeInfo.TrueNodes),
- (ConnectionInvokeType.IsFail, nodeInfo.FalseNodes),
- (ConnectionInvokeType.IsError, nodeInfo.ErrorNodes),
- (ConnectionInvokeType.Upstream, nodeInfo.UpstreamNodes)];
- foreach ((ConnectionInvokeType connectionType, string[] toNodeGuids) item in allToNodes)
+ foreach (var kvp in nodeInfo.SuccessorNodes)
{
+ var type = kvp.Key;
+ var nodes = kvp.Value;
+ if (nodes.Length == 0) continue;
// 遍历当前类型分支的节点(确认连接关系)
- foreach (var toNodeGuid in item.toNodeGuids)
+ foreach (var toNodeGuid in nodes)
{
if (!TryGetNodeModel(toNodeGuid, out var toNodeModel))
{
@@ -531,17 +531,76 @@ namespace Serein.NodeFlow.Env
// 防御性代码,加载正常保存的项目文件不会进入这里
continue;
}
-
- ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.NextStep, JunctionType.Execute, item.connectionType);
+ if (fromNodeModel.SuccessorNodes[type].Contains(toNodeModel) || toNodeModel.PreviousNodes[type].Contains(fromNodeModel))
+ {
+ continue;
+ }
+ ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.NextStep, JunctionType.Execute, type);
}
}
+ }
+
+ foreach (var nodeInfo in nodeInfos)
+ {
+ var canvasGuid = nodeInfo.CanvasGuid;
+ if (!TryGetNodeModel(nodeInfo.Guid, out var toNodeModel))
+ {
+ return;
+ }
+ if (toNodeModel is null) continue;
+ foreach (var kvp in nodeInfo.PreviousNodes)
+ {
+ var type = kvp.Key;
+ var nodes = kvp.Value;
+ if (nodes.Length == 0) continue;
+ // 遍历当前类型分支的节点(确认连接关系)
+ foreach (var toNodeGuid in nodes)
+ {
+ if (!TryGetNodeModel(toNodeGuid, out var fromNodeModel))
+ {
+ return;
+ }
+ if (toNodeModel is null)
+ {
+ // 防御性代码,加载正常保存的项目文件不会进入这里
+ continue;
+ }
+ if (fromNodeModel.SuccessorNodes[type].Contains(toNodeModel) || toNodeModel.PreviousNodes[type].Contains(fromNodeModel))
+ {
+ continue;
+ }
+ ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.NextStep, JunctionType.Execute, type);
+ }
+ }
+
}
+
#endregion
#region 确定节点之间的参数调用关系
- var nodeModels = flowModelService.GetAllNodeModel();
+ foreach (var nodeInfo in nodeInfos)
+ {
+ var pdInfos = nodeInfo.ParameterData;
+ var toNodeGuid = nodeInfo.Guid;
+ for (global::System.Int32 index = 0; index < pdInfos.Length; index++)
+ {
+ var pdInfo = pdInfos[index];
+ var fromNodeGuid = pdInfo.SourceNodeGuid;
+ if (!string.IsNullOrWhiteSpace(fromNodeGuid) && flowModelService.TryGetCanvasModel(fromNodeGuid,out var fromNode))
+ {
+ continue;
+ }
+ var type = EnumHelper.ConvertEnum(pdInfo.SourceType);
+ var canvasGuid = nodeInfo.CanvasGuid;
+ ConnectArgSourceNode(canvasGuid, fromNodeGuid, toNodeGuid, JunctionType.ReturnData, JunctionType.ArgData, type,index);
+
+ }
+ }
+
+
+ /* var nodeModels = flowModelService.GetAllNodeModel();
foreach (var toNode in nodeModels)
{
var canvasGuid = toNode.CanvasDetails.Guid;
@@ -555,10 +614,16 @@ namespace Serein.NodeFlow.Env
if (!string.IsNullOrEmpty(pd.ArgDataSourceNodeGuid)
&& TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var fromNode))
{
+ *//*if (fromNode.NeedResultNodes[pd.ArgDataSourceType].Contains(toNode)
+ && pd.ArgDataSourceNodeGuid == fromNode.Guid
+ && )
+ {
+ continue;
+ }*//*
ConnectArgSourceNode(canvasGuid, fromNode.Guid, toNode.Guid, JunctionType.ReturnData, JunctionType.ArgData, pd.ArgDataSourceType, pd.Index);
}
}
- }
+ }*/
#endregion
diff --git a/NodeFlow/Services/FlowCoreGenerateService.cs b/NodeFlow/Services/FlowCoreGenerateService.cs
index 6340a69..339af50 100644
--- a/NodeFlow/Services/FlowCoreGenerateService.cs
+++ b/NodeFlow/Services/FlowCoreGenerateService.cs
@@ -627,7 +627,7 @@ namespace Serein.NodeFlow.Services
// 初始化 Get 函数
var nodeIndexName = "node_index";
- sb.AppendCode(2, $" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); // 内联优化
+ //sb.AppendCode(2, $" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); // 内联优化
sb.AppendCode(2, $"public global::Serein.Library.CallNode {nameof(IFlowCallTree.Get)}( global::System.String key)");
sb.AppendCode(2, $"{{");
sb.AppendCode(3, $"global::System.Int32 {nodeIndexName};");
@@ -703,7 +703,6 @@ namespace Serein.NodeFlow.Services
}
-
private void GenerateFlowApi_ApiParamClass(StringBuilder sb)
{
var infos = flowApiMethodInfos.Values.ToArray();
@@ -887,6 +886,7 @@ namespace Serein.NodeFlow.Services
var contextImpleFullName = $"global::{typeof(DynamicContext).FullName}";
var tokenSourceFullName = $"global::{typeof(CancellationTokenSource).FullName}";
var tokenFullName = $"global::{typeof(CancellationToken).FullName}";
+ var flowContextPoolName = $"global::{typeof(LightweightFlowControl).FullName}";
string flowEnvironment = nameof(flowEnvironment);
string flowContext = nameof(flowContext);
string token = nameof(token);
@@ -902,11 +902,22 @@ namespace Serein.NodeFlow.Services
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({paramSignature})");
sb.AppendCode(2, $"{{");
- sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
- sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌");
- sb.AppendCode(3, $"await {ApiMethodName}({flowContext}, cts.Token, {invokeParamSignature}); // 调用目标方法");
- sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
- sb.AppendCode(3, $"cts.{nameof(CancellationTokenSource.Dispose)}(); ");
+ sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文");
+ sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌");
+ sb.AppendCode(3, $"try");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"await {ApiMethodName}({flowContext}, cts.Token, {invokeParamSignature}); // 调用目标方法");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"catch (Exception)");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"throw;");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"finally");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
+ sb.AppendCode(4, $"cts.{nameof(CancellationTokenSource.Dispose)}(); ");
+ sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
+ sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
@@ -916,9 +927,20 @@ namespace Serein.NodeFlow.Services
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({tokenFullName} {token}, {paramSignature})");
sb.AppendCode(2, $"{{");
- sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
- sb.AppendCode(3, $"await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法");
- sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
+ sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文");
+ sb.AppendCode(3, $"try");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法");
+ sb.AppendCode(4, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"catch (Exception)");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"throw;");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"finally");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
+ sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
@@ -930,21 +952,28 @@ namespace Serein.NodeFlow.Services
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({contextApiFullName} {flowContext}, {tokenFullName} token, {paramSignature})");
sb.AppendCode(2, $"{{");
- sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消");
- // 生成参数类实例化代码
- sb.AppendCode(3, $"global::{ParamTypeName} data = new global::{ParamTypeName}");
- sb.AppendCode(3, $"{{");
+ sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消");
+ sb.AppendCode(3, $"try");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(3, $"global::{ParamTypeName} data = {ObjPoolName}.Get(); // 从对象池获取一个对象");
for (int index = 0; index < ParamInfos.Count; index++)
{
ParamInfo? info = ParamInfos[index];
- sb.AppendCode(4, $"{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}");
+ sb.AppendCode(4, $"data.{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}");
}
- sb.AppendCode(3, $"}}");
-
- sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.AddOrUpdate)}(\"{ApiMethodName}\", data);");
- sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.SetPreviousNode)}(\"{NodeModel.Guid}\", \"{ApiMethodName}\");");
- sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");");
- sb.AppendCode(3, $"await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法");
+ sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.AddOrUpdate)}(\"{ApiMethodName}\", data);");
+ sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.SetPreviousNode)}(\"{NodeModel.TargetNode.Guid}\", \"{ApiMethodName}\");");
+ sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");");
+ sb.AppendCode(3, $"await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"catch (Exception)");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"throw;");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"finally");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
+ sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
@@ -954,16 +983,29 @@ namespace Serein.NodeFlow.Services
string flowResult = nameof(flowResult);
if (type == ParamType.Defute)
{
+ //sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
+
var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}"));
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({paramSignature})");
sb.AppendCode(2, $"{{");
- sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
- sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌");
- sb.AppendCode(3, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, cts.{nameof(CancellationTokenSource.Token)}, {invokeParamSignature}); // 调用目标方法");
- sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
- sb.AppendCode(3, $"cts.{nameof(CancellationTokenSource.Dispose)}(); ");
- sb.AppendCode(3, $"return {flowResult};");
+ sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文");
+ sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌");
+ sb.AppendCode(3, $"try");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, cts.{nameof(CancellationTokenSource.Token)}, {invokeParamSignature}); // 调用目标方法");
+ sb.AppendCode(4, $"return {flowResult};");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"catch (Exception)");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"throw;");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"finally");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
+ sb.AppendCode(4, $"cts.{nameof(CancellationTokenSource.Dispose)}(); ");
+ sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
+ sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
@@ -973,52 +1015,50 @@ namespace Serein.NodeFlow.Services
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({tokenFullName} {token}, {paramSignature})");
sb.AppendCode(2, $"{{");
- sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
- sb.AppendCode(3, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法");
- sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
- sb.AppendCode(3, $"return {flowResult};");
+ sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文");
+ sb.AppendCode(3, $"try");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法");
+ sb.AppendCode(4, $"return {flowResult};");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"catch (Exception)");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"throw;");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"finally");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
+ sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
+ sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
-
}
-
-
else if (type == ParamType.HasContextAndToken)
{
var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}"));
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({contextApiFullName} {flowContext}, {tokenFullName} token, {paramSignature})");
sb.AppendCode(2, $"{{");
- sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消");
- // 生成参数类实例化代码
- /*sb.AppendCode(3, $"global::{ParamTypeName} data = new global::{ParamTypeName}");
- sb.AppendCode(3, $"{{");
+ sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消");
+ sb.AppendCode(3, $"global::{ParamTypeName} data = {ObjPoolName}.Get(); // 从对象池获取一个对象");
for (int index = 0; index < ParamInfos.Count; index++)
{
ParamInfo? info = ParamInfos[index];
- sb.AppendCode(4, $"{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}");
+ sb.AppendCode(4, $"data.{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}"); // 进行赋值
}
- sb.AppendCode(3, $"}}");*/
- sb.AppendCode(3, $"global::{ParamTypeName} data = {ObjPoolName}.Get(); // 从对象池获取一个对象");
- for (int index = 0; index < ParamInfos.Count; index++)
- {
- ParamInfo? info = ParamInfos[index];
- sb.AppendCode(4, $"data.{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}");
- }
-
- sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.AddOrUpdate)}(\"{ApiMethodName}\", data);");
- sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.SetPreviousNode)}(\"{NodeModel.Guid}\", \"{ApiMethodName}\");");
- sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");");
- sb.AppendCode(3, $"global::{typeof(FlowResult).FullName} {flowResult} = await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法");
- sb.AppendCode(3, $"if ({flowResult}.{nameof(FlowResult.Value)} is global::{ReturnType.FullName} result)");
- sb.AppendCode(3, $"{{");
- sb.AppendCode(4, $"return result;");
- sb.AppendCode(3, $"}}");
- sb.AppendCode(3, $"else");
- sb.AppendCode(3, $"{{");
- sb.AppendCode(4, $"throw new ArgumentNullException($\"类型转换失败,{{(flowResult.Value is null ? \"返回数据为 null\" : $\"返回数据与需求类型不匹配,当前返回类型为[{{flowResult.Value.GetType().FullName}}。\")}}\");");
- sb.AppendCode(3, $"}}");
- sb.AppendCode(3, $"return {flowResult};");
+ sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.AddOrUpdate)}(\"{ApiMethodName}\", data);");
+ sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.SetPreviousNode)}(\"{NodeModel.Guid}\", \"{ApiMethodName}\");");
+ sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");");
+ sb.AppendCode(3, $"global::{typeof(FlowResult).FullName} {flowResult} = await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法");
+ sb.AppendCode(3, $"if ({flowResult}.{nameof(FlowResult.Value)} is global::{ReturnType.FullName} result)");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"return result;");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"else");
+ sb.AppendCode(3, $"{{");
+ sb.AppendCode(4, $"throw new ArgumentNullException($\"类型转换失败,{{(flowResult.Value is null ? \"返回数据为 null\" : $\"返回数据与需求类型不匹配,当前返回类型为[{{flowResult.Value.GetType().FullName}}。\")}}\");");
+ sb.AppendCode(3, $"}}");
+ sb.AppendCode(3, $"return {flowResult};");
sb.AppendCode(2, $"}}");
return sb.ToString();
// throw new ArgumentNullException($"类型转换失败,{(flowResult.Value is null ? "返回数据为 null" : $"返回数据与需求类型不匹配,当前返回类型为[{flowResult.Value.GetType().FullName}。")}");
diff --git a/Workbench/Converters/BoolToVisibilityConverter.cs b/Workbench/Converters/BoolToVisibilityConverter.cs
index 676924d..4e8b68f 100644
--- a/Workbench/Converters/BoolToVisibilityConverter.cs
+++ b/Workbench/Converters/BoolToVisibilityConverter.cs
@@ -14,7 +14,7 @@ namespace Serein.Workbench.Converters
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- Debug.WriteLine($"targetType:{targetType} value:{targetType} parameter:{parameter}");
+ //Debug.WriteLine($"targetType:{targetType} value:{targetType} parameter:{parameter}");
if (value is bool b)
{
return b ? Visibility.Visible : Visibility.Collapsed;