diff --git a/Library.Core/NodeFlow/DynamicContext.cs b/Library.Core/NodeFlow/DynamicContext.cs
index 96aa34c..7315912 100644
--- a/Library.Core/NodeFlow/DynamicContext.cs
+++ b/Library.Core/NodeFlow/DynamicContext.cs
@@ -30,6 +30,11 @@ namespace Serein.Library.Core.NodeFlow
///
public RunState RunState { get; set; } = RunState.NoStart;
+ ///
+ /// 当前节点执行完成后,设置该属性,让运行环境判断接下来要执行哪个分支的节点。
+ ///
+ public ConnectionInvokeType NextOrientation { get; set; }
+
///
/// 每个上下文分别存放节点的当前数据
///
diff --git a/Library.Framework/NodeFlow/DynamicContext.cs b/Library.Framework/NodeFlow/DynamicContext.cs
index 33a7020..711a87b 100644
--- a/Library.Framework/NodeFlow/DynamicContext.cs
+++ b/Library.Framework/NodeFlow/DynamicContext.cs
@@ -28,6 +28,12 @@ namespace Serein.Library.Framework.NodeFlow
/// 运行状态
///
public RunState RunState { get; set; } = RunState.NoStart;
+
+ ///
+ /// 当前节点执行完成后,设置该属性,让运行环境判断接下来要执行哪个分支的节点。
+ ///
+ public ConnectionInvokeType NextOrientation { get; set; }
+
///
/// 每个上下文分别存放节点的当前数据
///
diff --git a/Library/Api/IDynamicContext.cs b/Library/Api/IDynamicContext.cs
index f9ab472..925356a 100644
--- a/Library/Api/IDynamicContext.cs
+++ b/Library/Api/IDynamicContext.cs
@@ -15,8 +15,16 @@ namespace Serein.Library.Api
///
IFlowEnvironment Env { get; }
+ ///
+ /// 是否正在运行
+ ///
RunState RunState { get; }
+ ///
+ /// 下一个要执行的节点
+ ///
+ ConnectionInvokeType NextOrientation { get; set; }
+
///
/// 获取节点的数据(当前节点需要获取上一节点数据时,需要从 运行时上一节点 的Guid 通过这个方法进行获取
///
diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs
index fce88a0..c89a419 100644
--- a/Library/Api/IFlowEnvironment.cs
+++ b/Library/Api/IFlowEnvironment.cs
@@ -1,4 +1,5 @@
+
using Serein.Library.Utils;
using System;
using System.Collections.Generic;
@@ -175,12 +176,33 @@ namespace Serein.Library.Api
///
Remote,
}
- public NodeConnectChangeEventArgs(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType, ConnectChangeType changeType)
+ public NodeConnectChangeEventArgs(string fromNodeGuid,
+ string toNodeGuid,
+ JunctionOfConnectionType junctionOfConnectionType, // 指示需要创建什么类型的连接线
+ ConnectionInvokeType connectionInvokeType, // 节点调用的方法类型(true/false/error/cancel )
+ ConnectChangeType changeType) // 需要创建连接线还是删除连接线
{
this.FromNodeGuid = fromNodeGuid;
this.ToNodeGuid = toNodeGuid;
- this.ConnectionType = connectionType;
+ this.ConnectionInvokeType = connectionInvokeType;
this.ChangeType = changeType;
+ this.JunctionOfConnectionType = junctionOfConnectionType;
+ }
+
+ public NodeConnectChangeEventArgs(string fromNodeGuid,
+ string toNodeGuid,
+ JunctionOfConnectionType junctionOfConnectionType, // 指示需要创建什么类型的连接线
+ int argIndex,
+ ConnectionArgSourceType connectionArgSourceType, // 节点对应的方法入参所需参数来源
+ ConnectChangeType changeType) // 需要创建连接线还是删除连接线
+ {
+ this.FromNodeGuid = fromNodeGuid;
+ this.ToNodeGuid = toNodeGuid;
+ this.ChangeType = changeType;
+ this.ArgIndex = argIndex;
+ this.ConnectionArgSourceType = connectionArgSourceType;
+ this.JunctionOfConnectionType = junctionOfConnectionType;
+
}
///
/// 连接关系中始节点的Guid
@@ -193,11 +215,22 @@ namespace Serein.Library.Api
///
/// 连接类型
///
- public ConnectionType ConnectionType { get; protected set; }
+ public ConnectionInvokeType ConnectionInvokeType { get; protected set; }
///
/// 表示此次需要在两个节点之间创建连接关系,或是移除连接关系
///
public ConnectChangeType ChangeType { get; protected set; }
+ ///
+ /// 指示需要创建什么类型的连接线
+ ///
+ public JunctionOfConnectionType JunctionOfConnectionType { get; protected set; }
+ ///
+ /// 节点对应的方法入参所需参数来源
+ ///
+ public ConnectionArgSourceType ConnectionArgSourceType { get; protected set; }
+ public int ArgIndex { get; protected set; }
+
+
}
@@ -639,6 +672,13 @@ namespace Serein.Library.Api
///
Task StartAsyncInSelectNode(string startNodeGuid);
+ ///
+ /// 立刻调用某个节点,并获取其返回值
+ ///
+ /// 节点Guid
+ ///
+ Task
/// 起始节点Guid
/// 目标节点Guid
- /// 连接类型
- Task ConnectNodeAsync(string fromNodeGuid, string toNodeGuid, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType, ConnectionType connectionType);
+ /// 起始节点控制点
+ /// 目标节点控制点
+ /// 决定了方法执行后的后继行为
+ /// 决定了方法入参来源
+ Task ConnectNodeAsync(string fromNodeGuid,
+ string toNodeGuid,
+ JunctionType fromNodeJunctionType,
+ JunctionType toNodeJunctionType,
+ ConnectionInvokeType connectionType,
+ int argIndex);
///
/// 创建节点/区域/基础控件
@@ -680,7 +728,7 @@ namespace Serein.Library.Api
/// 起始节点
/// 目标节点
/// 连接类型
- Task RemoveConnectAsync(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType);
+ Task RemoveConnectAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType);
///
/// 移除节点/区域/基础控件
diff --git a/Library/Enums/ConnectionArgSourceType.cs b/Library/Enums/ConnectionArgSourceType.cs
new file mode 100644
index 0000000..c985604
--- /dev/null
+++ b/Library/Enums/ConnectionArgSourceType.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Serein.Library
+{
+
+ ///
+ /// 节点对应方法的入参来源
+ ///
+ public enum ConnectionArgSourceType
+ {
+ ///
+ /// (连接自身)从上一节点获取数据
+ ///
+ GetPreviousNodeData,
+ ///
+ /// 从指定节点获取数据
+ ///
+ GetOtherNodeData,
+ ///
+ /// 立刻执行某个节点获取其数据
+ ///
+ GetOtherNodeDataOfInvoke,
+ }
+}
diff --git a/Library/Enums/ConnectionType.cs b/Library/Enums/ConnectionInvokeType.cs
similarity index 88%
rename from Library/Enums/ConnectionType.cs
rename to Library/Enums/ConnectionInvokeType.cs
index 9412f99..568fe8d 100644
--- a/Library/Enums/ConnectionType.cs
+++ b/Library/Enums/ConnectionInvokeType.cs
@@ -8,7 +8,7 @@ namespace Serein.Library
///
/// 表示了两个节点之间的连接关系,同时表示节点运行完成后,所会执行的下一个节点类型。
///
- public enum ConnectionType
+ public enum ConnectionInvokeType
{
///
/// 将不会继续执行
@@ -30,11 +30,8 @@ namespace Serein.Library
/// 异常发生分支(当前节点对应的方法执行时出现非预期的异常)
///
IsError,
- ///
- /// 无视
- ///
- // IsIgnore,
}
-
+
+
}
diff --git a/Library/Enums/JunctionOfConnectionType.cs b/Library/Enums/JunctionOfConnectionType.cs
new file mode 100644
index 0000000..c2790ff
--- /dev/null
+++ b/Library/Enums/JunctionOfConnectionType.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Serein.Library
+{
+ ///
+ /// 连接的控制点类型枚举
+ ///
+ public enum JunctionOfConnectionType
+ {
+ ///
+ /// 没有关系,用于处理非预期连接的情况需要的返回值
+ ///
+ None,
+ ///
+ /// 表示方法执行顺序关系
+ ///
+ Invoke,
+ ///
+ /// 表示参数获取来源关系
+ ///
+ Arg
+ }
+}
diff --git a/Library/Enums/JunctionType.cs b/Library/Enums/JunctionType.cs
index 83941fb..805d930 100644
--- a/Library/Enums/JunctionType.cs
+++ b/Library/Enums/JunctionType.cs
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Serein.Library
{
///
- /// 连接点类型
+ /// 控制点类型
///
public enum JunctionType
{
@@ -28,4 +28,8 @@ namespace Serein.Library
///
NextStep,
}
+
+
+
+
}
diff --git a/Library/FlowNode/JunctionModel.cs b/Library/FlowNode/JunctionModel.cs
new file mode 100644
index 0000000..6fbf28e
--- /dev/null
+++ b/Library/FlowNode/JunctionModel.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Serein.Library.FlowNode
+{
+
+
+ /*
+ * 有1个Execute
+ * 有1个NextStep
+ * 有0~65535个入参 ushort
+ * 有1个ReturnData(void方法返回null)
+ *
+ * Execute: // 执行这个方法
+ * 只接受 NextStep 的连接
+ * ArgData:
+ * 互相之间不能连接,只能接受 Execute、ReturnData 的连接
+ * Execute:表示从 Execute所在节点 获取数据
+ * ReturnData: 表示从对应节点获取数据
+ * ReturnData:
+ * 只能发起主动连接,且只能连接到 ArgData
+ * NextStep
+ * 只能连接连接 Execute
+ *
+ */
+
+ ///
+ /// 依附于节点的连接点
+ ///
+ public class JunctionModel
+ {
+ public JunctionModel(NodeModelBase NodeModel, JunctionType JunctionType)
+ {
+ Guid = System.Guid.NewGuid().ToString();
+ this.NodeModel = NodeModel;
+ this.JunctionType = JunctionType;
+ }
+ ///
+ /// 用于标识连接点
+ ///
+ public string Guid { get; }
+
+ ///
+ /// 标识连接点的类型
+ ///
+ public JunctionType JunctionType { get; }
+
+ ///
+ /// 连接点依附的节点
+ ///
+ public NodeModelBase NodeModel { get; }
+ }
+}
diff --git a/Library/FlowNode/NodeModelBaseData.cs b/Library/FlowNode/NodeModelBaseData.cs
index 5021a68..061d4dd 100644
--- a/Library/FlowNode/NodeModelBaseData.cs
+++ b/Library/FlowNode/NodeModelBaseData.cs
@@ -3,6 +3,7 @@ using Serein.Library.NodeGenerator;
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Net.Mime;
using System.Threading;
namespace Serein.Library
@@ -71,8 +72,8 @@ namespace Serein.Library
///
/// 当前节点执行完毕后需要执行的下一个分支的类别
///
- [PropertyInfo]
- private ConnectionType _nextOrientation = ConnectionType.None;
+ //[PropertyInfo]
+ //private ConnectionInvokeType _nextOrientation = ConnectionInvokeType.None;
///
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
@@ -91,9 +92,9 @@ namespace Serein.Library
{
public NodeModelBase(IFlowEnvironment environment)
{
- PreviousNodes = new Dictionary>();
- SuccessorNodes = new Dictionary>();
- foreach (ConnectionType ctType in NodeStaticConfig.ConnectionTypes)
+ PreviousNodes = new Dictionary>();
+ SuccessorNodes = new Dictionary>();
+ foreach (ConnectionInvokeType ctType in NodeStaticConfig.ConnectionTypes)
{
PreviousNodes[ctType] = new List();
SuccessorNodes[ctType] = new List();
@@ -102,15 +103,17 @@ namespace Serein.Library
this.Env = environment;
}
+
+
///
/// 不同分支的父节点
///
- public Dictionary> PreviousNodes { get; }
+ public Dictionary> PreviousNodes { get; }
///
/// 不同分支的子节点
///
- public Dictionary> SuccessorNodes { get; }
+ public Dictionary> SuccessorNodes { get; }
///
diff --git a/Library/FlowNode/NodeModelBaseFunc.cs b/Library/FlowNode/NodeModelBaseFunc.cs
index 0a3ae20..9893174 100644
--- a/Library/FlowNode/NodeModelBaseFunc.cs
+++ b/Library/FlowNode/NodeModelBaseFunc.cs
@@ -6,6 +6,7 @@ using Serein.Library.Utils.SereinExpression;
using System;
using System.Collections;
using System.Collections.Generic;
+using System.ComponentModel.Design;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http.Headers;
@@ -24,22 +25,6 @@ namespace Serein.Library
///
public abstract partial class NodeModelBase : IDynamicFlowNode
{
-
-
- #region 调试中断
-
-
- ///
- /// 不再中断
- ///
- public void CancelInterrupt()
- {
- this.DebugSetting.InterruptClass = InterruptClass.None;
- DebugSetting.CancelInterruptCallback?.Invoke();
- }
-
- #endregion
-
#region 导出/导入项目文件节点信息
///
@@ -56,10 +41,10 @@ namespace Serein.Library
{
// if (MethodDetails == null) return null;
- var trueNodes = SuccessorNodes[ConnectionType.IsSucceed].Select(item => item.Guid); // 真分支
- var falseNodes = SuccessorNodes[ConnectionType.IsFail].Select(item => item.Guid);// 假分支
- var errorNodes = SuccessorNodes[ConnectionType.IsError].Select(item => item.Guid);// 异常分支
- var upstreamNodes = SuccessorNodes[ConnectionType.Upstream].Select(item => item.Guid);// 上游分支
+ var trueNodes = SuccessorNodes[ConnectionInvokeType.IsSucceed].Select(item => item.Guid); // 真分支
+ var falseNodes = SuccessorNodes[ConnectionInvokeType.IsFail].Select(item => item.Guid);// 假分支
+ var errorNodes = SuccessorNodes[ConnectionInvokeType.IsError].Select(item => item.Guid);// 异常分支
+ var upstreamNodes = SuccessorNodes[ConnectionInvokeType.Upstream].Select(item => item.Guid);// 上游分支
// 生成参数列表
Parameterdata[] parameterData = GetParameterdatas();
@@ -86,7 +71,7 @@ namespace Serein.Library
///
public virtual NodeModelBase LoadInfo(NodeInfo nodeInfo)
{
- this.Guid = nodeInfo.Guid;
+ this.Guid = nodeInfo.Guid;
if (nodeInfo.Position is null)
{
@@ -104,6 +89,19 @@ namespace Serein.Library
}
return this;
}
+ #endregion
+
+ #region 调试中断
+
+
+ ///
+ /// 不再中断
+ ///
+ public void CancelInterrupt()
+ {
+ this.DebugSetting.InterruptClass = InterruptClass.None;
+ DebugSetting.CancelInterruptCallback?.Invoke();
+ }
#endregion
@@ -137,8 +135,6 @@ namespace Serein.Library
return false;
}
-
-
///
/// 开始执行
///
@@ -163,7 +159,7 @@ namespace Serein.Library
var currentNode = stack.Pop();
// 筛选出上游分支
- var upstreamNodes = currentNode.SuccessorNodes[ConnectionType.Upstream].ToArray();
+ var upstreamNodes = currentNode.SuccessorNodes[ConnectionInvokeType.Upstream].ToArray();
for (int index = 0; index < upstreamNodes.Length; index++)
{
NodeModelBase upstreamNode = upstreamNodes[index];
@@ -176,7 +172,7 @@ namespace Serein.Library
}
upstreamNode.PreviousNode = currentNode;
await upstreamNode.StartFlowAsync(context); // 执行流程节点的上游分支
- if (upstreamNode.NextOrientation == ConnectionType.IsError)
+ if (context.NextOrientation == ConnectionInvokeType.IsError)
{
// 如果上游分支执行失败,不再继续执行
// 使上游节点(仅上游节点本身,不包含上游节点的后继节点)
@@ -197,7 +193,7 @@ namespace Serein.Library
#region 执行完成
// 选择后继分支
- var nextNodes = currentNode.SuccessorNodes[currentNode.NextOrientation];
+ var nextNodes = currentNode.SuccessorNodes[context.NextOrientation];
// 将下一个节点集合中的所有节点逆序推入栈中
for (int i = nextNodes.Count - 1; i >= 0; i--)
@@ -215,7 +211,6 @@ namespace Serein.Library
}
}
-
///
/// 执行节点对应的方法
///
@@ -234,7 +229,6 @@ namespace Serein.Library
#endregion
MethodDetails md = MethodDetails;
- //var del = md.MethodDelegate.Clone();
if (md is null)
{
throw new Exception($"节点{this.Guid}不存在方法信息,请检查是否需要重写节点的ExecutingAsync");
@@ -247,35 +241,70 @@ namespace Serein.Library
{
md.ActingInstance = context.Env.IOC.Get(md.ActingInstanceType);
}
- // md.ActingInstance ??= context.Env.IOC.Get(md.ActingInstanceType);
- object instance = md.ActingInstance;
-
-
- object result = null;
-
try
{
- object[] args = GetParameters(context, this, md);
- result = await dd.InvokeAsync(md.ActingInstance, args);
- NextOrientation = ConnectionType.IsSucceed;
+ object[] args = await GetParametersAsync(context, this, md);
+ var result = await dd.InvokeAsync(md.ActingInstance, args);
+ context.NextOrientation = ConnectionInvokeType.IsSucceed;
return result;
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync($"节点[{this.MethodDetails?.MethodName}]异常:" + ex);
- NextOrientation = ConnectionType.IsError;
+ context.NextOrientation = ConnectionInvokeType.IsError;
RuningException = ex;
return null;
}
}
+ ///
+ /// 执行单个节点对应的方法,并不做状态检查
+ ///
+ ///
+ ///
+ public virtual async Task