diff --git a/Library/Api/IDynamicContext.cs b/Library/Api/IDynamicContext.cs
index db5b973..dcb1b81 100644
--- a/Library/Api/IDynamicContext.cs
+++ b/Library/Api/IDynamicContext.cs
@@ -54,22 +54,21 @@ namespace Serein.Library.Api
///
/// 获取节点的数据(当前节点需要获取上一节点数据时,需要从 运行时上一节点 的Guid 通过这个方法进行获取
///
- ///
+ ///
///
- object GetFlowData(string nodeGuid);
-
+ FlowResult GetFlowData(NodeModelBase nodeModel);
///
/// 上一节点数据透传到下一节点
///
///
- object TransmissionData(NodeModelBase nodeModel);
+ FlowResult TransmissionData(NodeModelBase nodeModel);
///
/// 添加或更新当前节点的数据
///
- ///
+ ///
///
- void AddOrUpdate(string nodeGuid, object flowData);
+ void AddOrUpdate(NodeModelBase nodeModel, FlowResult flowData);
///
/// 重置流程状态(用于对象池回收)
diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs
index 4cf05e8..172b81a 100644
--- a/Library/Api/IFlowEnvironment.cs
+++ b/Library/Api/IFlowEnvironment.cs
@@ -950,6 +950,13 @@ namespace Serein.Library.Api
#endregion
#region 流程运行相关
+ ///
+ /// 获取节点信息
+ ///
+ ///
+ ///
+ ///
+ bool TryGetNodeModel(string nodeGuid, out NodeModelBase nodeModel);
///
/// 获取方法描述信息
@@ -1026,7 +1033,7 @@ namespace Serein.Library.Api
/// 调用时的上下文
/// 节点Guid
///
- Task
public static class ConvertHelper
{
+ ///
+ /// 字面量转为对应类型
+ ///
+ ///
+ ///
+ public static Type ToTypeOfString(this string valueStr)
+ {
+ if (valueStr.IndexOf('.') != -1)
+ {
+ // 通过指定的类型名称获取类型
+ return Type.GetType(valueStr);
+ }
+
+
+ if (valueStr.Equals("bool", StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(bool);
+ }
+ #region 整数型
+ else if (valueStr.Equals("sbyte", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(SByte), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(SByte);
+ }
+ else if (valueStr.Equals("short", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(Int16), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(Int16);
+ }
+ else if (valueStr.Equals("int", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(Int32), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(Int32);
+ }
+ else if (valueStr.Equals("long", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(Int64), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(Int64);
+ }
+
+ else if (valueStr.Equals("byte", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(Byte), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(Byte);
+ }
+ else if (valueStr.Equals("ushort", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(UInt16), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(UInt16);
+ }
+ else if (valueStr.Equals("uint", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(UInt32), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(UInt32);
+ }
+ else if (valueStr.Equals("ulong", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(UInt64), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(UInt64);
+ }
+ #endregion
+
+ #region 浮点型
+ else if (valueStr.Equals("float", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(Single), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(Single);
+ }
+ else if (valueStr.Equals("double", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(Double), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(Double);
+ }
+ #endregion
+
+ #region 小数型
+
+ else if (valueStr.Equals("decimal", StringComparison.OrdinalIgnoreCase)
+ || valueStr.Equals(nameof(Decimal), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(Decimal);
+ }
+ #endregion
+
+ #region 其他常见的类型
+ else if (valueStr.Equals(nameof(DateTime), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(DateTime);
+ }
+
+ else if (valueStr.Equals(nameof(String), StringComparison.OrdinalIgnoreCase))
+ {
+ return typeof(String);
+ }
+ #endregion
+
+ else
+ {
+ throw new ArgumentException($"无法解析的字面量类型[{valueStr}]");
+ }
+ }
+
+
///
/// 对象转JSON文本
diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs
index 4c0787e..6a7010f 100644
--- a/NodeFlow/Env/FlowEnvironment.cs
+++ b/NodeFlow/Env/FlowEnvironment.cs
@@ -392,7 +392,7 @@ namespace Serein.NodeFlow.Env
IOC.Reset();
IOC.Register(); // 注册脚本接口
- var flowTaskOptions = new FlowTaskLibrary
+ var flowTaskOptions = new FlowWorkLibrary
{
Environment = this,
@@ -440,8 +440,8 @@ namespace Serein.NodeFlow.Env
}
if (true || FlowState == RunState.Running || FlipFlopState == RunState.Running)
{
- NodeModelBase? nodeModel = GuidToModel(startNodeGuid);
- if (nodeModel is null || nodeModel is SingleFlipflopNode)
+
+ if (!TryGetNodeModel(startNodeGuid,out var nodeModel) || nodeModel is SingleFlipflopNode)
{
return false;
}
@@ -460,14 +460,14 @@ namespace Serein.NodeFlow.Env
}
}
- ///
+ /*///
/// 单独运行一个节点
///
///
///
public async Task InvokeNodeAsync(IDynamicContext context, string nodeGuid)
{
- object result = new Unit();
+ object result = Unit.Default;
if (this.NodeModels.TryGetValue(nodeGuid, out var model))
{
CancellationTokenSource cts = new CancellationTokenSource();
@@ -475,7 +475,7 @@ namespace Serein.NodeFlow.Env
cts?.Cancel();
}
return result;
- }
+ }*/
///
/// 结束流程
@@ -496,7 +496,10 @@ namespace Serein.NodeFlow.Env
///
public void ActivateFlipflopNode(string nodeGuid)
{
- var nodeModel = GuidToModel(nodeGuid);
+ if(!TryGetNodeModel(nodeGuid, out var nodeModel))
+ {
+ return;
+ }
if (nodeModel is null) return;
if (flowTaskManagement is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
{
@@ -515,7 +518,10 @@ namespace Serein.NodeFlow.Env
///
public void TerminateFlipflopNode(string nodeGuid)
{
- var nodeModel = GuidToModel(nodeGuid);
+ if(!TryGetNodeModel(nodeGuid, out var nodeModel))
+ {
+ return;
+ }
if (nodeModel is null) return;
if (flowTaskManagement is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
{
@@ -858,7 +864,10 @@ namespace Serein.NodeFlow.Env
#region 确定节点之间的方法调用关系
foreach (var nodeInfo in nodeInfos)
{
- var fromNodeModel = GuidToModel(nodeInfo.Guid);
+ if (!TryGetNodeModel(nodeInfo.Guid, out var fromNodeModel))
+ {
+ return;
+ }
if (fromNodeModel is null) continue;
List<(ConnectionInvokeType connectionType, string[] guids)> allToNodes = [(ConnectionInvokeType.IsSucceed,nodeInfo.TrueNodes),
(ConnectionInvokeType.IsFail, nodeInfo.FalseNodes),
@@ -869,7 +878,10 @@ namespace Serein.NodeFlow.Env
// 遍历当前类型分支的节点(确认连接关系)
foreach (var toNodeGuid in item.toNodeGuids)
{
- var toNodeModel = GuidToModel(toNodeGuid);
+ if (!TryGetNodeModel(toNodeGuid, out var toNodeModel))
+ {
+ return;
+ }
if (toNodeModel is null) {
// 防御性代码,加载正常保存的项目文件不会进入这里
continue;
@@ -915,7 +927,7 @@ namespace Serein.NodeFlow.Env
&& NodeModels.TryGetValue(pd.ArgDataSourceNodeGuid, out var fromNode))
{
- _ = ConnectArgSourceOfNodeAsync(fromNode, toNode, pd.ArgDataSourceType, pd.Index);
+ await ConnectArgSourceOfNodeAsync(fromNode, toNode, pd.ArgDataSourceType, pd.Index);
}
}
}
@@ -981,20 +993,24 @@ namespace Serein.NodeFlow.Env
/// 将节点放置在容器中
///
///
- public async Task PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid)
+ public Task PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid)
{
// 获取目标节点与容器节点
- var nodeModel = GuidToModel(nodeGuid);
- if (nodeModel is null ) return false;
-
- if(nodeModel.ContainerNode is INodeContainer tmpContainer)
+ if (!TryGetNodeModel(nodeGuid, out var nodeModel))
+ {
+ return Task.FromResult(false);
+ }
+ if (nodeModel.ContainerNode is INodeContainer tmpContainer)
{
SereinEnv.WriteLine(InfoType.WARN, $"节点放置失败,节点[{nodeGuid}]已经放置于容器节点[{((NodeModelBase)tmpContainer).Guid}]");
- return false;
+ return Task.FromResult(false);
}
- var containerNode = GuidToModel(containerNodeGuid); // 获取容器节点
- if (containerNode is not INodeContainer nodeContainer) return false;
+ if (!TryGetNodeModel(containerNodeGuid, out var containerNode))
+ {
+ return Task.FromResult(false);
+ }
+ if (containerNode is not INodeContainer nodeContainer) return Task.FromResult(false);
var result = nodeContainer.PlaceNode(nodeModel); // 放置在容器节点
if (result)
@@ -1004,7 +1020,7 @@ namespace Serein.NodeFlow.Env
OnNodePlace?.Invoke(new NodePlaceEventArgs(nodeGuid, containerNodeGuid)); // 通知UI更改节点放置位置
});
}
- return result;
+ return Task.FromResult(result);
}
@@ -1012,15 +1028,16 @@ namespace Serein.NodeFlow.Env
/// 将节点从容器节点中脱离
///
///
- public async Task TakeOutNodeToContainerAsync(string nodeGuid)
+ public Task TakeOutNodeToContainerAsync(string nodeGuid)
{
// 获取目标节点与容器节点
- var nodeModel = GuidToModel(nodeGuid);
- if (nodeModel is null) return false;
-
- if(nodeModel.ContainerNode is not INodeContainer nodeContainer)
+ if (!TryGetNodeModel(nodeGuid, out var nodeModel))
{
- return false;
+ return Task.FromResult(false);
+ }
+ if (nodeModel.ContainerNode is not INodeContainer nodeContainer)
+ {
+ return Task.FromResult(false);
}
var result = nodeContainer.TakeOutNode(nodeModel); // 从容器节点取出
if (result)
@@ -1030,7 +1047,7 @@ namespace Serein.NodeFlow.Env
OnNodeTakeOut?.Invoke(new NodeTakeOutEventArgs(nodeGuid)); // 重新放置在画布上
});
}
- return result;
+ return Task.FromResult(result);
}
@@ -1044,9 +1061,10 @@ namespace Serein.NodeFlow.Env
///
public async Task RemoveNodeAsync(string nodeGuid)
{
- var remoteNode = GuidToModel(nodeGuid);
- if (remoteNode is null)
- return false;
+ if (!TryGetNodeModel(nodeGuid, out var remoteNode))
+ {
+ return false;
+ }
if (remoteNode is SingleFlipflopNode flipflopNode)
{
@@ -1103,7 +1121,7 @@ namespace Serein.NodeFlow.Env
/// 起始节点控制点
/// 目标节点控制点
/// 连接关系
- public async Task ConnectInvokeNodeAsync(string fromNodeGuid,
+ public Task ConnectInvokeNodeAsync(string fromNodeGuid,
string toNodeGuid,
JunctionType fromNodeJunctionType,
JunctionType toNodeJunctionType,
@@ -1111,17 +1129,19 @@ namespace Serein.NodeFlow.Env
{
// 获取起始节点与目标节点
- var fromNode = GuidToModel(fromNodeGuid);
- var toNode = GuidToModel(toNodeGuid);
- if (fromNode is null || toNode is null) return false;
+ if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
+ {
+ return Task.FromResult(false);
+ }
+
+ if (fromNode is null || toNode is null) return Task.FromResult(false);
(var type, var state) = CheckConnect(fromNode, toNode, fromNodeJunctionType, toNodeJunctionType);
if (!state)
{
SereinEnv.WriteLine(InfoType.WARN, "出现非预期的连接行为");
- return false; // 出现不符预期的连接行为,忽略此次连接行为
+ return Task.FromResult(false); // 出现不符预期的连接行为,忽略此次连接行为
}
-
if(type == JunctionOfConnectionType.Invoke)
{
if (fromNodeJunctionType == JunctionType.Execute)
@@ -1132,7 +1152,7 @@ namespace Serein.NodeFlow.Env
// 从起始节点“下一个方法”控制点,连接到目标节点“方法调用”控制点
state = ConnectInvokeOfNode(fromNode, toNode, invokeType); // 本地环境进行连接
}
- return state;
+ return Task.FromResult(state);
}
@@ -1147,8 +1167,10 @@ namespace Serein.NodeFlow.Env
public Task SetConnectPriorityInvoke(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
{
// 获取起始节点与目标节点
- var fromNode = GuidToModel(fromNodeGuid);
- var toNode = GuidToModel(toNodeGuid);
+ if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
+ {
+ return Task.FromResult(false);
+ }
if (fromNode is null || toNode is null) return Task.FromResult(false);
if ( fromNode.SuccessorNodes.TryGetValue(connectionType, out var nodes))
{
@@ -1173,8 +1195,10 @@ namespace Serein.NodeFlow.Env
public async Task RemoveConnectInvokeAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
{
// 获取起始节点与目标节点
- var fromNode = GuidToModel(fromNodeGuid);
- var toNode = GuidToModel(toNodeGuid);
+ if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
+ {
+ return false;
+ }
if (fromNode is null || toNode is null) return false;
var result = await RemoteConnectAsync(fromNode, toNode, connectionType);
@@ -1200,8 +1224,10 @@ namespace Serein.NodeFlow.Env
{
// 获取起始节点与目标节点
- var fromNode = GuidToModel(fromNodeGuid);
- var toNode = GuidToModel(toNodeGuid);
+ if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
+ {
+ return false;
+ }
if (fromNode is null || toNode is null) return false;
(var type, var state) = CheckConnect(fromNode, toNode, fromNodeJunctionType, toNodeJunctionType);
if (!state)
@@ -1236,8 +1262,10 @@ namespace Serein.NodeFlow.Env
public async Task RemoveConnectArgSourceAsync(string fromNodeGuid, string toNodeGuid, int argIndex)
{
// 获取起始节点与目标节点
- var fromNode = GuidToModel(fromNodeGuid);
- var toNode = GuidToModel(toNodeGuid);
+ if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
+ {
+ return false;
+ }
if (fromNode is null || toNode is null) return false;
var result = await RemoteConnectAsync(fromNode, toNode, argIndex);
return result;
@@ -1302,10 +1330,11 @@ namespace Serein.NodeFlow.Env
///
public void MoveNode(string nodeGuid, double x, double y)
{
- NodeModelBase? nodeModel = GuidToModel(nodeGuid);
- if (nodeModel is null) return;
+ if (!TryGetNodeModel(nodeGuid, out var nodeModel))
+ {
+ return;
+ }
nodeModel.Position.X = x;
-
nodeModel.Position.Y = y;
UIContextOperation?.Invoke(() => OnNodeMoved?.Invoke(new NodeMovedEventArgs(nodeGuid, x, y)));
@@ -1317,9 +1346,10 @@ namespace Serein.NodeFlow.Env
///
public Task SetStartNodeAsync(string newNodeGuid)
{
- var newStartNodeModel = GuidToModel(newNodeGuid);
- if (newStartNodeModel is null)
- return Task.FromResult(StartNode?.Guid ?? string.Empty);
+ if (!TryGetNodeModel(newNodeGuid, out var newStartNodeModel))
+ {
+ return Task.FromResult(StartNode?.Guid ?? string.Empty);
+ }
SetStartNode(newStartNodeModel);
return Task.FromResult(StartNode?.Guid ?? string.Empty);
}
@@ -1370,12 +1400,13 @@ namespace Serein.NodeFlow.Env
/// 属性路径
/// 变化后的属性值
///
- public async Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
+ public Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
{
- var nodeModel = GuidToModel(nodeGuid);
- if (nodeModel is null) return;
- SerinExpressionEvaluator.Evaluate($"@Set .{path} = {value}", nodeModel, out _); // 更改对应的数据
-
+ if (TryGetNodeModel(nodeGuid, out var nodeModel))
+ {
+ SerinExpressionEvaluator.Evaluate($"@Set .{path} = {value}", nodeModel, out _); // 更改对应的数据
+ }
+ return Task.CompletedTask;
//if (NodeValueChangeLogger.Remove((nodeGuid, path, value)))
//{
// // 说明存在过重复的修改
@@ -1414,7 +1445,10 @@ namespace Serein.NodeFlow.Env
///
public Task ChangeParameter(string nodeGuid, bool isAdd, int paramIndex)
{
- var nodeModel = GuidToModel(nodeGuid);
+ if (!TryGetNodeModel(nodeGuid, out var nodeModel))
+ {
+ return Task.FromResult(false);
+ }
if (nodeModel is null) return Task.FromResult(false);
bool isPass;
if (isAdd)
@@ -1429,30 +1463,26 @@ namespace Serein.NodeFlow.Env
}
+
///
/// Guid 转 NodeModel
///
/// 节点Guid
/// 节点Model
/// 无法获取节点、Guid/节点为null时报错
- private NodeModelBase? GuidToModel(string nodeGuid)
+ public bool TryGetNodeModel(string nodeGuid,out NodeModelBase nodeModel)
{
if (string.IsNullOrEmpty(nodeGuid))
{
- //throw new ArgumentNullException("not contains - Guid没有对应节点:" + (nodeGuid));
- return null;
+ nodeModel = null;
+ return false;
}
- if (!NodeModels.TryGetValue(nodeGuid, out NodeModelBase? nodeModel) || nodeModel is null)
- {
- //throw new ArgumentNullException("null - Guid存在对应节点,但节点为null:" + (nodeGuid));
- return null;
- }
- return nodeModel;
+ return NodeModels.TryGetValue(nodeGuid, out nodeModel) && nodeModel is not null;
+
}
#endregion
-
#region 流程依赖类库的接口
diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs
index 8cc8b48..fdc2aa0 100644
--- a/NodeFlow/Env/FlowEnvironmentDecorator.cs
+++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs
@@ -492,10 +492,7 @@ namespace Serein.NodeFlow.Env
return await currentFlowEnvironment.StartAsyncInSelectNode(startNodeGuid);
}
- public async Task InvokeNodeAsync(IDynamicContext context, string nodeGuid)
- {
- return await currentFlowEnvironment.InvokeNodeAsync(context, nodeGuid);
- }
+
public async Task StartRemoteServerAsync(int port = 7525)
{
@@ -524,6 +521,11 @@ namespace Serein.NodeFlow.Env
{
currentFlowEnvironment.SetUIContextOperation(uiContextOperation);
}
+
+ public bool TryGetNodeModel(string nodeGuid, out NodeModelBase nodeModel)
+ {
+ return currentFlowEnvironment.TryGetNodeModel(nodeGuid, out nodeModel);
+ }
public bool TryGetDelegateDetails(string libraryName, string methodName, out DelegateDetails del)
{
return currentFlowEnvironment.TryGetDelegateDetails(libraryName, methodName, out del);
diff --git a/NodeFlow/Env/RemoteFlowEnvironment.cs b/NodeFlow/Env/RemoteFlowEnvironment.cs
index e0d63b9..bddb9c6 100644
--- a/NodeFlow/Env/RemoteFlowEnvironment.cs
+++ b/NodeFlow/Env/RemoteFlowEnvironment.cs
@@ -1217,14 +1217,13 @@ namespace Serein.NodeFlow.Env
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:SetMonitorObjState");
}
- public async Task InvokeNodeAsync(IDynamicContext context, string nodeGuid)
- {
- // 登录到远程环境后,启动器相关方法无效
- this.WriteLine(InfoType.INFO, "远程环境尚未实现接口 InvokeNodeAsync");
- return null;
- }
-
+ public bool TryGetNodeModel(string nodeGuid, out NodeModelBase nodeModel)
+ {
+ this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:TryGetNodeModel");
+ nodeModel = null;
+ return false;
+ }
public bool TryGetMethodDetailsInfo(string libraryName, string methodName, out MethodDetailsInfo mdInfo)
{
diff --git a/NodeFlow/FlowTaskLibrary.cs b/NodeFlow/FlowWorkLibrary.cs
similarity index 93%
rename from NodeFlow/FlowTaskLibrary.cs
rename to NodeFlow/FlowWorkLibrary.cs
index f6eb5c1..2e0ec1f 100644
--- a/NodeFlow/FlowTaskLibrary.cs
+++ b/NodeFlow/FlowWorkLibrary.cs
@@ -9,8 +9,10 @@ using System.Threading.Tasks;
namespace Serein.NodeFlow
{
-
- public class FlowTaskLibrary()
+ ///
+ /// 节点任务执行依赖
+ ///
+ public class FlowWorkLibrary()
{
///
/// 流程运行环境
diff --git a/NodeFlow/FlowWorkManagement.cs b/NodeFlow/FlowWorkManagement.cs
index 2953505..3d697ed 100644
--- a/NodeFlow/FlowWorkManagement.cs
+++ b/NodeFlow/FlowWorkManagement.cs
@@ -30,13 +30,13 @@ namespace Serein.NodeFlow
///
/// 初始化选项
///
- public FlowTaskLibrary WorkLibrary { get; }
+ public FlowWorkLibrary WorkLibrary { get; }
///
/// 流程任务管理
///
///
- public FlowWorkManagement(FlowTaskLibrary library)
+ public FlowWorkManagement(FlowWorkLibrary library)
{
WorkLibrary = library;
@@ -301,7 +301,7 @@ namespace Serein.NodeFlow
{
var context = pool.Allocate(); // 启动全局触发器时新建上下文
var newFlowData = await singleFlipFlopNode.ExecutingAsync(context, singleToken); // 获取触发器等待Task
- context.AddOrUpdate(singleFlipFlopNode.Guid, newFlowData);
+ context.AddOrUpdate(singleFlipFlopNode, newFlowData);
if (context.NextOrientation == ConnectionInvokeType.None)
{
continue;
@@ -326,6 +326,14 @@ namespace Serein.NodeFlow
}
+ ///
+ /// 全局触发器触发后的调用
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
private static async Task? CallSubsequentNode(SingleFlipflopNode singleFlipFlopNode, CancellationToken singleToken, ObjectPool pool, IDynamicContext context)
{
var flowState = context.NextOrientation; // 记录一下流程状态
diff --git a/NodeFlow/Model/CompositeConditionNode.cs b/NodeFlow/Model/CompositeConditionNode.cs
index 23212a2..520dd08 100644
--- a/NodeFlow/Model/CompositeConditionNode.cs
+++ b/NodeFlow/Model/CompositeConditionNode.cs
@@ -36,7 +36,7 @@ namespace Serein.NodeFlow.Model
///
///
///
- public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
+ public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
{
try
{
@@ -45,7 +45,7 @@ namespace Serein.NodeFlow.Model
{
if (token.IsCancellationRequested)
{
- return null;
+ return new FlowResult(this, context);
}
var state = await node.ExecutingAsync(context, token);
if (context.NextOrientation != ConnectionInvokeType.IsSucceed)
@@ -56,7 +56,8 @@ namespace Serein.NodeFlow.Model
}
//var previousNode = context.GetPreviousNode()
- return context.TransmissionData(this); // 条件区域透传上一节点的数据
+ var result = context.TransmissionData(this); // 条件区域透传上一节点的数据
+ return new FlowResult(this,context, result);
}
catch (Exception ex)
{
diff --git a/NodeFlow/Model/SingleConditionNode.cs b/NodeFlow/Model/SingleConditionNode.cs
index 64f4dbd..ac1b76e 100644
--- a/NodeFlow/Model/SingleConditionNode.cs
+++ b/NodeFlow/Model/SingleConditionNode.cs
@@ -110,9 +110,12 @@ namespace Serein.NodeFlow.Model
///
///
///
- public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
+ public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
{
- if (token.IsCancellationRequested) return null;
+ if (token.IsCancellationRequested)
+ {
+ return new FlowResult(this, context);
+ }
// 接收上一节点参数or自定义参数内容
object? parameter;
object? result = null;
@@ -121,17 +124,31 @@ namespace Serein.NodeFlow.Model
{
// 使用自动取参
var pd = MethodDetails.ParameterDetailss[INDEX_EXPRESSION];
+ var hasNode = context.Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var argSourceNode);
+ if (hasNode)
+ {
+ context.NextOrientation = ConnectionInvokeType.IsError;
+ return new FlowResult(this, context);
+ }
+ if (hasNode)
+ {
+ return new FlowResult(this, context);
+ }
if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
{
- result = context.GetFlowData(pd.ArgDataSourceNodeGuid); // 使用自定义节点的参数
+ result = context.GetFlowData(argSourceNode).Value; // 使用自定义节点的参数
}
else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
{
- result = await Env.InvokeNodeAsync(context, pd.ArgDataSourceNodeGuid); // 立刻调用目标节点,然后使用其返回值
+ CancellationTokenSource cts = new CancellationTokenSource();
+ var nodeResult = await argSourceNode.ExecutingAsync(context, cts.Token);
+ result = nodeResult.Value;
+ cts?.Cancel();
+ cts?.Dispose();
}
else
{
- result = context.TransmissionData(this); // 条件节点透传上一节点的数据
+ result = context.TransmissionData(this).Value; // 条件节点透传上一节点的数据
}
parameter = result; // 使用上一节点的参数
@@ -167,7 +184,7 @@ namespace Serein.NodeFlow.Model
SereinEnv.WriteLine(InfoType.INFO, $"{result} {Expression} -> " + context.NextOrientation);
//return result;
- return judgmentResult;
+ return new FlowResult(this, context, judgmentResult);
}
diff --git a/NodeFlow/Model/SingleExpOpNode.cs b/NodeFlow/Model/SingleExpOpNode.cs
index 8935cbf..9b07721 100644
--- a/NodeFlow/Model/SingleExpOpNode.cs
+++ b/NodeFlow/Model/SingleExpOpNode.cs
@@ -92,22 +92,32 @@ namespace Serein.NodeFlow.Model
}
- public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
+ public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
{
- if(token.IsCancellationRequested) return null;
+ if(token.IsCancellationRequested) return new FlowResult(this, context);
object? parameter = null;// context.TransmissionData(this); // 表达式节点使用上一节点数据
var pd = MethodDetails.ParameterDetailss[0];
+ var hasNode = context.Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var argSourceNode);
+ if (hasNode)
+ {
+ context.NextOrientation = ConnectionInvokeType.IsError;
+ return new FlowResult(this, context);
+ }
if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
{
// 使用自定义节点的参数
- parameter = context.GetFlowData(pd.ArgDataSourceNodeGuid);
+ parameter = context.GetFlowData(argSourceNode).Value;
}
else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
{
// 立刻调用目标节点,然后使用其返回值
- parameter = await Env.InvokeNodeAsync(context, pd.ArgDataSourceNodeGuid);
+ var cts = new CancellationTokenSource();
+ var result = await argSourceNode.ExecutingAsync(context, cts.Token);
+ cts?.Cancel();
+ cts?.Dispose();
+ parameter = result.Value;
}
else
{
@@ -129,13 +139,13 @@ namespace Serein.NodeFlow.Model
}
context.NextOrientation = ConnectionInvokeType.IsSucceed;
- return result;
+ return new FlowResult(this,context, result);
}
catch (Exception ex)
{
context.NextOrientation = ConnectionInvokeType.IsError;
context.ExceptionOfRuning = ex;
- return parameter;
+ return new FlowResult(this, context);
}
}
diff --git a/NodeFlow/Model/SingleFlipflopNode.cs b/NodeFlow/Model/SingleFlipflopNode.cs
index e68d5aa..f20f15c 100644
--- a/NodeFlow/Model/SingleFlipflopNode.cs
+++ b/NodeFlow/Model/SingleFlipflopNode.cs
@@ -22,7 +22,7 @@ namespace Serein.NodeFlow.Model
///
///
///
- public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
+ public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
{
#region 执行前中断
if (DebugSetting.IsInterrupt) // 执行触发前
@@ -40,8 +40,13 @@ namespace Serein.NodeFlow.Model
}
var instance = context.Env.IOC.Get(md.ActingInstanceType);
+ if (instance is null)
+ {
+ Env.IOC.Register(md.ActingInstanceType).Build();
+ instance = Env.IOC.Get(md.ActingInstanceType);
+ }
await dd.InvokeAsync(instance, [context]);
- var args = await GetParametersAsync(context, token);
+ var args = await this.GetParametersAsync(context, token);
// 因为这里会返回不确定的泛型 IFlipflopContext
// 而我们只需要获取到 State 和 Value(返回的数据)
// 所以使用 dynamic 类型接收
@@ -58,7 +63,9 @@ namespace Serein.NodeFlow.Model
{
throw new FlipflopException(base.MethodDetails.MethodName + "触发器超时触发。Guid" + base.Guid);
}
- return dynamicFlipflopContext.Value;
+ object result = dynamicFlipflopContext.Value;
+ var flowReslt = new FlowResult(this, context, result);
+ return flowReslt;
}
}
diff --git a/NodeFlow/Model/SingleGlobalDataNode.cs b/NodeFlow/Model/SingleGlobalDataNode.cs
index 2e3f063..aff7795 100644
--- a/NodeFlow/Model/SingleGlobalDataNode.cs
+++ b/NodeFlow/Model/SingleGlobalDataNode.cs
@@ -115,33 +115,34 @@ namespace Serein.NodeFlow.Model
///
///
///
- public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
+ public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
{
- if (token.IsCancellationRequested) return null;
+ if (token.IsCancellationRequested) return new FlowResult(this, context);
if (string.IsNullOrEmpty(KeyName))
{
context.NextOrientation = ConnectionInvokeType.IsError;
SereinEnv.WriteLine(InfoType.ERROR, $"全局数据的KeyName不能为空[{this.Guid}]");
- return null;
+ return new FlowResult(this, context);
}
if (DataNode is null)
{
context.NextOrientation = ConnectionInvokeType.IsError;
SereinEnv.WriteLine(InfoType.ERROR, $"全局数据节点没有设置数据来源[{this.Guid}]");
- return null;
+ return new FlowResult(this, context);
}
try
{
- var result = await context.Env.InvokeNodeAsync(context, DataNode.Guid);
- SereinEnv.AddOrUpdateFlowGlobalData(KeyName, result);
+
+ var result = await DataNode.ExecutingAsync(context, token);
+ SereinEnv.AddOrUpdateFlowGlobalData(KeyName, result.Value);
return result;
}
catch (Exception ex)
{
context.NextOrientation = ConnectionInvokeType.IsError;
context.ExceptionOfRuning = ex;
- return null;
+ return new FlowResult(this, context);
}
}
diff --git a/NodeFlow/Model/SingleScriptNode.cs b/NodeFlow/Model/SingleScriptNode.cs
index a0f6129..e9f6f16 100644
--- a/NodeFlow/Model/SingleScriptNode.cs
+++ b/NodeFlow/Model/SingleScriptNode.cs
@@ -165,12 +165,11 @@ namespace Serein.NodeFlow.Model
///
///
///
- public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
+ public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
{
- if(token.IsCancellationRequested) return null;
- var @params = await GetParametersAsync(context, token);
- if(token.IsCancellationRequested) return null;
-
+ if (token.IsCancellationRequested) return new FlowResult(this, context);
+ var @params = await this.GetParametersAsync(context, token);
+ if(token.IsCancellationRequested) return new FlowResult(this, context);
//context.AddOrUpdate($"{context.Guid}_{this.Guid}_Params", @params[0]); // 后面再改
ReloadScript();// 每次都重新解析
@@ -199,9 +198,9 @@ namespace Serein.NodeFlow.Model
if (token.IsCancellationRequested) return null;
var result = await ScriptInterpreter.InterpretAsync(scriptContext, mainNode); // 从入口节点执行
- envEvent.OnFlowRunComplete -= onFlowStop;
+ envEvent.OnFlowRunComplete -= onFlowStop;
+ return new FlowResult(this, context, result);
//SereinEnv.WriteLine(InfoType.INFO, "FlowContext Guid : " + context.Guid);
- return result;
}
diff --git a/NodeFlow/Model/SingleUINode.cs b/NodeFlow/Model/SingleUINode.cs
index bbf7955..42111b8 100644
--- a/NodeFlow/Model/SingleUINode.cs
+++ b/NodeFlow/Model/SingleUINode.cs
@@ -15,14 +15,14 @@ namespace Serein.NodeFlow.Model
{
}
- public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
+ public override async Task ExecutingAsync(IDynamicContext context, CancellationToken token)
{
- if (token.IsCancellationRequested) return null;
+ if (token.IsCancellationRequested) return new FlowResult(this,context);
if(Adapter is null)
{
var result = await base.ExecutingAsync(context, token);
- if (result is IEmbeddedContent adapter)
+ if (result.Value is IEmbeddedContent adapter)
{
this.Adapter = adapter;
context.NextOrientation = ConnectionInvokeType.IsSucceed;
@@ -35,12 +35,12 @@ namespace Serein.NodeFlow.Model
else
{
var p = context.GetPreviousNode(this);
- var data = context.GetFlowData(p.Guid);
+ var data = context.GetFlowData(p).Value;
var iflowContorl = Adapter.GetFlowControl();
iflowContorl.OnExecuting(data);
}
-
- return null;
+
+ return new FlowResult(this, context);
}
}
}
diff --git a/NodeFlow/ScriptFlowApi.cs b/NodeFlow/ScriptFlowApi.cs
index c6bf14f..325a976 100644
--- a/NodeFlow/ScriptFlowApi.cs
+++ b/NodeFlow/ScriptFlowApi.cs
@@ -42,22 +42,21 @@ namespace Serein.NodeFlow
throw new NotImplementedException();
}
- public object? GetArgData(IDynamicContext context, int index)
- {
- var _paramsKey = $"{context?.Guid}_{NodeModel.Guid}_Params";
- var obj = context?.GetFlowData(_paramsKey);
- if (obj is object[] @params && index < @params.Length)
- {
- return @params[index];
- }
- return null;
- }
+ //public object? GetArgData(IDynamicContext context, int index)
+ //{
+ // var _paramsKey = $"{context?.Guid}_{NodeModel.Guid}_Params";
+ // var obj = context?.GetFlowData(_paramsKey);
+ // if (obj is object[] @params && index < @params.Length)
+ // {
+ // return @params[index];
+ // }
+ // return null;
+ //}
-
- public object? GetFlowData(IDynamicContext context)
- {
- return context?.GetFlowData(NodeModel.Guid);
- }
+ //public object? GetFlowData(IDynamicContext context)
+ //{
+ // return context?.GetFlowData(NodeModel.Guid);
+ //}
public object? GetGlobalData(string keyName)
{
diff --git a/Serein.Script/SereinScriptParser.cs b/Serein.Script/SereinScriptParser.cs
index 63505ee..6827674 100644
--- a/Serein.Script/SereinScriptParser.cs
+++ b/Serein.Script/SereinScriptParser.cs
@@ -1,5 +1,6 @@
using Newtonsoft.Json.Linq;
using Serein.Library;
+using Serein.Library.Utils;
using Serein.Script.Node;
using System.Collections.Generic;
using System.Linq.Expressions;
diff --git a/Serein.Workbench.Avalonia/Custom/Views/NodeJunctionView.axaml.cs b/Serein.Workbench.Avalonia/Custom/Views/NodeJunctionView.axaml.cs
index eac6477..cdd561d 100644
--- a/Serein.Workbench.Avalonia/Custom/Views/NodeJunctionView.axaml.cs
+++ b/Serein.Workbench.Avalonia/Custom/Views/NodeJunctionView.axaml.cs
@@ -136,7 +136,7 @@ public class NodeJunctionView : TemplatedControl
nodeOperationService.ConnectingManage.Reset();
}
- private void CheckJunvtion()
+ private async void CheckJunvtion()
{
var myData = nodeOperationService.ConnectingManage;
if(myData.StartJunction is null || myData.CurrentJunction is null)
@@ -157,7 +157,7 @@ public class NodeJunctionView : TemplatedControl
#region ùϵ
if (myData.Type == JunctionOfConnectionType.Invoke)
{
- flowEnvironment.ConnectInvokeNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
+ await flowEnvironment.ConnectInvokeNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
myData.StartJunction.JunctionType,
myData.CurrentJunction.JunctionType,
myData.ConnectionInvokeType);
@@ -177,7 +177,7 @@ public class NodeJunctionView : TemplatedControl
argIndex = myData.CurrentJunction.ArgIndex;
}
- flowEnvironment.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
+ await flowEnvironment.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
myData.StartJunction.JunctionType,
myData.CurrentJunction.JunctionType,
myData.ConnectionArgSourceType,
diff --git a/Workbench/MainWindow.xaml.cs b/Workbench/MainWindow.xaml.cs
index 12101fd..9c63b62 100644
--- a/Workbench/MainWindow.xaml.cs
+++ b/Workbench/MainWindow.xaml.cs
@@ -1944,7 +1944,7 @@ namespace Serein.Workbench
///
///
///
- private void FlowChartCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ private async void FlowChartCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (IsSelectControl)
{
@@ -1975,7 +1975,7 @@ namespace Serein.Workbench
#region 方法调用关系创建
if (myData.Type == JunctionOfConnectionType.Invoke)
{
- this.EnvDecorator.ConnectInvokeNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
+ await EnvDecorator.ConnectInvokeNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
myData.StartJunction.JunctionType,
myData.CurrentJunction.JunctionType,
myData.ConnectionInvokeType);
@@ -1995,7 +1995,7 @@ namespace Serein.Workbench
argIndex = argJunction2.ArgIndex;
}
- this.EnvDecorator.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
+ await EnvDecorator.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
myData.StartJunction.JunctionType,
myData.CurrentJunction.JunctionType,
myData.ConnectionArgSourceType,
diff --git a/Workbench/Node/View/UINodeControl.xaml.cs b/Workbench/Node/View/UINodeControl.xaml.cs
index 5ba5aa5..4d7beac 100644
--- a/Workbench/Node/View/UINodeControl.xaml.cs
+++ b/Workbench/Node/View/UINodeControl.xaml.cs
@@ -54,7 +54,6 @@ namespace Serein.Workbench.Node.View
EmbedContainer.Child = userControl;
});
-
}
private void NodeControlBase_Initialized(object sender, EventArgs e)
diff --git a/Workbench/Node/ViewModel/UINodeControlViewModel.cs b/Workbench/Node/ViewModel/UINodeControlViewModel.cs
index 40e74cf..e7a9b3b 100644
--- a/Workbench/Node/ViewModel/UINodeControlViewModel.cs
+++ b/Workbench/Node/ViewModel/UINodeControlViewModel.cs
@@ -26,7 +26,7 @@ namespace Serein.Workbench.Node.ViewModel
{
var context = new DynamicContext(NodeModel.Env);
var cts = new CancellationTokenSource();
- await NodeModel.ExecutingAsync(context, cts.Token);
+ var result = await NodeModel.ExecutingAsync(context, cts.Token);
cts?.Dispose();
if (context.NextOrientation == ConnectionInvokeType.IsSucceed
&& NodeModel.Adapter.GetUserControl() is UserControl userControl)
diff --git a/Workbench/Views/FlowCanvasView.xaml.cs b/Workbench/Views/FlowCanvasView.xaml.cs
index 73d8a09..bcfa112 100644
--- a/Workbench/Views/FlowCanvasView.xaml.cs
+++ b/Workbench/Views/FlowCanvasView.xaml.cs
@@ -309,7 +309,7 @@ namespace Serein.Workbench.Views
///
///
///
- private void FlowChartCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
+ private async void FlowChartCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (IsSelectControl)
{
@@ -340,7 +340,7 @@ namespace Serein.Workbench.Views
#region 方法调用关系创建
if (myData.Type == JunctionOfConnectionType.Invoke)
{
- this.EnvDecorator.ConnectInvokeNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
+ await EnvDecorator.ConnectInvokeNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
myData.StartJunction.JunctionType,
myData.CurrentJunction.JunctionType,
myData.ConnectionInvokeType);
@@ -360,7 +360,7 @@ namespace Serein.Workbench.Views
argIndex = argJunction2.ArgIndex;
}
- this.EnvDecorator.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
+ await EnvDecorator.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
myData.StartJunction.JunctionType,
myData.CurrentJunction.JunctionType,
myData.ConnectionArgSourceType,