mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
对象预览器支持了值类型集合成员的简单预览
This commit is contained in:
@@ -9,12 +9,12 @@ namespace Serein.NodeFlow.Base
|
||||
/// </summary>
|
||||
public abstract partial class NodeModelBase :IDynamicFlowNode
|
||||
{
|
||||
private static readonly ConnectionType[] ct = [ConnectionType.IsSucceed,
|
||||
ConnectionType.IsFail,
|
||||
ConnectionType.IsError,
|
||||
ConnectionType.Upstream];
|
||||
public NodeModelBase()
|
||||
{
|
||||
ConnectionType[] ct = [ConnectionType.IsSucceed,
|
||||
ConnectionType.IsFail,
|
||||
ConnectionType.IsError,
|
||||
ConnectionType.Upstream];
|
||||
PreviousNodes = [];
|
||||
SuccessorNodes = [];
|
||||
foreach (ConnectionType ctType in ct)
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Serein.NodeFlow.Base
|
||||
{
|
||||
Stack<NodeModelBase> stack = new Stack<NodeModelBase>();
|
||||
stack.Push(this);
|
||||
var cts = context.SereinIoc.Get<CancellationTokenSource>(FlowStarter.FlipFlopCtsName);
|
||||
var cts = context.Env.IOC.Get<CancellationTokenSource>(FlowStarter.FlipFlopCtsName);
|
||||
while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环
|
||||
{
|
||||
// 节点执行异常时跳过执行
|
||||
@@ -109,7 +109,7 @@ namespace Serein.NodeFlow.Base
|
||||
// 设置方法执行的对象
|
||||
if (currentNode.MethodDetails?.ActingInstance == null && currentNode.MethodDetails?.ActingInstanceType is not null)
|
||||
{
|
||||
currentNode.MethodDetails.ActingInstance ??= context.SereinIoc.GetOrRegisterInstantiate(currentNode.MethodDetails.ActingInstanceType);
|
||||
currentNode.MethodDetails.ActingInstance ??= context.Env.IOC.GetOrRegisterInstantiate(currentNode.MethodDetails.ActingInstanceType);
|
||||
}
|
||||
|
||||
#region 执行相关
|
||||
@@ -330,52 +330,139 @@ namespace Serein.NodeFlow.Base
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新节点数据,并检查监视表达式
|
||||
/// 更新节点数据,并检查监视表达式是否生效
|
||||
/// </summary>
|
||||
/// <param name="newData"></param>
|
||||
public static async Task RefreshFlowDataAndExpInterrupt(IDynamicContext context, NodeModelBase nodeModel, object? newData = null)
|
||||
public static async Task RefreshFlowDataAndExpInterrupt(IDynamicContext context,NodeModelBase nodeModel, object? newData = null)
|
||||
{
|
||||
|
||||
string guid = nodeModel.Guid;
|
||||
// 检查是否存在监视表达式
|
||||
if (newData is not null && nodeModel.DebugSetting.InterruptExpressions.Count > 0)
|
||||
if(newData is not null)
|
||||
{
|
||||
// 表达式环境下判断是否需要执行中断
|
||||
bool isExpInterrupt = false;
|
||||
string? exp = "";
|
||||
// 判断执行监视表达式,直到为 true 时退出
|
||||
for (int i = 0; i < nodeModel.DebugSetting.InterruptExpressions.Count && !isExpInterrupt; i++)
|
||||
{
|
||||
exp = nodeModel.DebugSetting.InterruptExpressions[i];
|
||||
isExpInterrupt = SereinConditionParser.To(newData, exp);
|
||||
}
|
||||
|
||||
if (isExpInterrupt) // 触发中断
|
||||
{
|
||||
InterruptClass interruptClass = InterruptClass.Branch; // 分支中断
|
||||
if (context.FlowEnvironment.SetNodeInterrupt(nodeModel.Guid, interruptClass))
|
||||
{
|
||||
context.FlowEnvironment.TriggerInterrupt(guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Exp);
|
||||
var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
|
||||
await Console.Out.WriteLineAsync($"[{nodeModel.MethodDetails.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
}
|
||||
|
||||
}
|
||||
await MonitorObjExpInterrupt(context, nodeModel, newData, 0); // 首先监视对象
|
||||
await MonitorObjExpInterrupt(context, nodeModel, newData, 1); // 然后监视节点
|
||||
nodeModel.FlowData = newData; // 替换数据
|
||||
}
|
||||
|
||||
|
||||
|
||||
//if(context.Env.CheckObjMonitorState(newData, out List<string> exps)) // 如果新的数据处于查看状态,通知UI进行更新?交给运行环境判断?
|
||||
//{
|
||||
// context.Env.MonitorObjectNotification(guid, newData); // 对象处于监视状态,通知UI更新数据显示
|
||||
// if (exps.Count > 0)
|
||||
// {
|
||||
// // 表达式环境下判断是否需要执行中断
|
||||
// bool isExpInterrupt = false;
|
||||
// string? exp = "";
|
||||
// // 判断执行监视表达式,直到为 true 时退出
|
||||
// for (int i = 0; i < exps.Count && !isExpInterrupt; i++)
|
||||
// {
|
||||
// exp = exps[i];
|
||||
// isExpInterrupt = SereinConditionParser.To(newData, exp);
|
||||
// }
|
||||
|
||||
// if (isExpInterrupt) // 触发中断
|
||||
// {
|
||||
// InterruptClass interruptClass = InterruptClass.Branch; // 分支中断
|
||||
// if (context.Env.SetNodeInterrupt(nodeModel.Guid, interruptClass))
|
||||
// {
|
||||
// context.Env.TriggerInterrupt(guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Obj);
|
||||
// var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
|
||||
// await Console.Out.WriteLineAsync($"[{newData}]中断已{cancelType},开始执行后继分支");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
//if (newData is not null && nodeModel.DebugSetting.InterruptExpressions.Count > 0) // 检查节点是否存在监视表达式
|
||||
//{
|
||||
// // 表达式环境下判断是否需要执行中断
|
||||
// bool isExpInterrupt = false;
|
||||
// string? exp = "";
|
||||
// // 判断执行监视表达式,直到为 true 时退出
|
||||
// for (int i = 0; i < nodeModel.DebugSetting.InterruptExpressions.Count && !isExpInterrupt; i++)
|
||||
// {
|
||||
// exp = nodeModel.DebugSetting.InterruptExpressions[i];
|
||||
// isExpInterrupt = SereinConditionParser.To(newData, exp);
|
||||
// }
|
||||
|
||||
// if (isExpInterrupt) // 触发中断
|
||||
// {
|
||||
// InterruptClass interruptClass = InterruptClass.Branch; // 分支中断
|
||||
// if (context.Env.SetNodeInterrupt(nodeModel.Guid, interruptClass))
|
||||
// {
|
||||
// context.Env.TriggerInterrupt(guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Exp);
|
||||
// var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
|
||||
// await Console.Out.WriteLineAsync($"[{nodeModel.MethodDetails.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
// }
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
//else if (nodeModel.DebugSetting.InterruptClass != InterruptClass.None)
|
||||
//{
|
||||
// var cancelType = await nodeModel.DebugSetting.InterruptTask;
|
||||
// await Console.Out.WriteLineAsync($"[{nodeModel.MethodDetails.MethodName}]中断已{(cancelType == CancelType.Manual ? "手动取消" : "自动取消")},开始执行后继分支");
|
||||
//}
|
||||
|
||||
nodeModel.FlowData = newData; // 替换数据
|
||||
// 节点是否监视了数据,如果是,调用环境接口触发其相关事件。
|
||||
if (nodeModel.DebugSetting.IsMonitorFlowData)
|
||||
|
||||
|
||||
//if (nodeModel.DebugSetting.IsMonitorFlowData)
|
||||
//{
|
||||
// // 节点是否监视了数据,如果是,调用环境接口触发其相关事件。
|
||||
// context.Env.FlowDataNotification(guid, newData);
|
||||
//}
|
||||
}
|
||||
|
||||
private static async Task MonitorObjExpInterrupt(IDynamicContext context, NodeModelBase nodeModel, object data, int type)
|
||||
{
|
||||
MonitorObjectEventArgs.ObjSourceType sourceType;
|
||||
object key;
|
||||
if(type == 0)
|
||||
{
|
||||
context.FlowEnvironment.FlowDataNotification(guid, newData);
|
||||
key = data;
|
||||
sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = nodeModel.Guid;
|
||||
sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
|
||||
|
||||
}
|
||||
if (context.Env.CheckObjMonitorState(key, out List<string> exps)) // 如果新的数据处于查看状态,通知UI进行更新?交给运行环境判断?
|
||||
{
|
||||
context.Env.MonitorObjectNotification(nodeModel.Guid, data, sourceType); // 对象处于监视状态,通知UI更新数据显示
|
||||
if (exps.Count > 0)
|
||||
{
|
||||
// 表达式环境下判断是否需要执行中断
|
||||
bool isExpInterrupt = false;
|
||||
string? exp = "";
|
||||
// 判断执行监视表达式,直到为 true 时退出
|
||||
for (int i = 0; i < exps.Count && !isExpInterrupt; i++)
|
||||
{
|
||||
exp = exps[i];
|
||||
isExpInterrupt = SereinConditionParser.To(data, exp);
|
||||
}
|
||||
|
||||
if (isExpInterrupt) // 触发中断
|
||||
{
|
||||
InterruptClass interruptClass = InterruptClass.Branch; // 分支中断
|
||||
if (context.Env.SetNodeInterrupt(nodeModel.Guid, interruptClass))
|
||||
{
|
||||
context.Env.TriggerInterrupt(nodeModel.Guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Obj);
|
||||
var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
|
||||
await Console.Out.WriteLineAsync($"[{data}]中断已{cancelType},开始执行后继分支");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 释放对象
|
||||
|
||||
@@ -8,6 +8,7 @@ using Serein.Library.Utils;
|
||||
using Serein.NodeFlow.Base;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.NodeFlow.Tool;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
@@ -41,10 +42,11 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 运行环境
|
||||
/// </summary>
|
||||
public class FlowEnvironment : IFlowEnvironment
|
||||
public class FlowEnvironment : IFlowEnvironment, ISereinIOC
|
||||
{
|
||||
public FlowEnvironment()
|
||||
{
|
||||
sereinIOC = new SereinIOC();
|
||||
ChannelFlowInterrupt = new ChannelFlowInterrupt();
|
||||
LoadedAssemblyPaths = new List<string>();
|
||||
LoadedAssemblies = new List<Assembly>();
|
||||
@@ -113,6 +115,8 @@ namespace Serein.NodeFlow
|
||||
|
||||
#endregion
|
||||
|
||||
#region 属性
|
||||
|
||||
/// <summary>
|
||||
/// 环境名称
|
||||
/// </summary>
|
||||
@@ -121,38 +125,46 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 是否全局中断
|
||||
/// </summary>
|
||||
public bool IsGlobalInterrupt { get; set; }
|
||||
public bool IsGlobalInterrupt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 流程中断器
|
||||
/// </summary>
|
||||
public ChannelFlowInterrupt ChannelFlowInterrupt { get; set; }
|
||||
|
||||
|
||||
public ISereinIOC IOC { get => this; }
|
||||
#endregion
|
||||
|
||||
#region 私有变量
|
||||
/// <summary>
|
||||
/// 容器管理
|
||||
/// </summary>
|
||||
private SereinIOC sereinIOC;
|
||||
|
||||
/// <summary>
|
||||
/// 存储加载的程序集路径
|
||||
/// </summary>
|
||||
public List<string> LoadedAssemblyPaths { get; }
|
||||
private List<string> LoadedAssemblyPaths { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 存储加载的程序集
|
||||
/// </summary>
|
||||
public List<Assembly> LoadedAssemblies { get; }
|
||||
private List<Assembly> LoadedAssemblies { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 存储所有方法信息
|
||||
/// </summary>
|
||||
public List<MethodDetails> MethodDetailss { get; }
|
||||
private List<MethodDetails> MethodDetailss { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 环境加载的节点集合
|
||||
/// </summary>
|
||||
public Dictionary<string, NodeModelBase> Nodes { get; }
|
||||
private Dictionary<string, NodeModelBase> Nodes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 存放触发器节点(运行时全部调用)
|
||||
/// </summary>
|
||||
public List<SingleFlipflopNode> FlipflopNodes { get; }
|
||||
private List<SingleFlipflopNode> FlipflopNodes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点私有属性
|
||||
@@ -162,7 +174,7 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 起始节点
|
||||
/// </summary>
|
||||
public NodeModelBase StartNode
|
||||
private NodeModelBase StartNode
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -171,7 +183,7 @@ namespace Serein.NodeFlow
|
||||
set
|
||||
{
|
||||
if (_startNode is not null)
|
||||
{
|
||||
{
|
||||
_startNode.IsStart = false;
|
||||
}
|
||||
value.IsStart = true;
|
||||
@@ -179,12 +191,16 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程启动器(每次运行时都会重新new一个)
|
||||
/// </summary>
|
||||
private FlowStarter? flowStarter;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 对外暴露的接口
|
||||
|
||||
/// <summary>
|
||||
/// 异步运行
|
||||
/// </summary>
|
||||
@@ -204,13 +220,34 @@ namespace Serein.NodeFlow
|
||||
|
||||
await flowStarter.RunAsync(this, nodes, initMethods, loadingMethods, exitMethods);
|
||||
|
||||
if(flowStarter?.FlipFlopState == RunState.NoStart)
|
||||
if (flowStarter?.FlipFlopState == RunState.NoStart)
|
||||
{
|
||||
this.Exit(); // 未运行触发器时,才会调用结束方法
|
||||
}
|
||||
flowStarter = null;
|
||||
}
|
||||
|
||||
public async Task StartFlowInSelectNodeAsync(string startNodeGuid)
|
||||
{
|
||||
if (flowStarter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (flowStarter.FlowState == RunState.Running || flowStarter.FlipFlopState == RunState.Running)
|
||||
{
|
||||
NodeModelBase? nodeModel = GuidToModel(startNodeGuid);
|
||||
if (nodeModel is null || nodeModel is SingleFlipflopNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
await flowStarter.StartFlowInSelectNodeAsync(nodeModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出
|
||||
/// </summary>
|
||||
@@ -221,7 +258,7 @@ namespace Serein.NodeFlow
|
||||
|
||||
foreach (var node in Nodes.Values)
|
||||
{
|
||||
if(node is not null)
|
||||
if (node is not null)
|
||||
{
|
||||
node.ReleaseFlowData(); // 退出时释放对象计数
|
||||
}
|
||||
@@ -244,32 +281,6 @@ namespace Serein.NodeFlow
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行环节加载了项目文件,需要创建节点控件
|
||||
/// </summary>
|
||||
/// <param name="nodeInfo"></param>
|
||||
/// <param name="methodDetailss"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private NodeControlType GetNodeControlType(NodeInfo nodeInfo)
|
||||
{
|
||||
// 创建控件实例
|
||||
NodeControlType controlType = nodeInfo.Type switch
|
||||
{
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleActionNode)}" => NodeControlType.Action,// 动作节点控件
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleFlipflopNode)}" => NodeControlType.Flipflop, // 触发器节点控件
|
||||
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleConditionNode)}" => NodeControlType.ExpCondition,// 条件表达式控件
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleExpOpNode)}" => NodeControlType.ExpOp, // 操作表达式控件
|
||||
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(CompositeConditionNode)}" => NodeControlType.ConditionRegion, // 条件区域控件
|
||||
_ => NodeControlType.None,
|
||||
};
|
||||
|
||||
return controlType;
|
||||
}
|
||||
|
||||
#region 对外暴露的接口
|
||||
|
||||
/// <summary>
|
||||
/// 加载项目文件
|
||||
@@ -304,7 +315,7 @@ namespace Serein.NodeFlow
|
||||
foreach (var nodeInfo in project.Nodes)
|
||||
{
|
||||
var controlType = GetNodeControlType(nodeInfo);
|
||||
if(controlType == NodeControlType.None)
|
||||
if (controlType == NodeControlType.None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -319,9 +330,9 @@ namespace Serein.NodeFlow
|
||||
continue;
|
||||
}
|
||||
TryAddNode(nodeModel);
|
||||
if(nodeInfo.ChildNodeGuids?.Length > 0)
|
||||
if (nodeInfo.ChildNodeGuids?.Length > 0)
|
||||
{
|
||||
regionChildNodes.Add((nodeModel,nodeInfo.ChildNodeGuids));
|
||||
regionChildNodes.Add((nodeModel, nodeInfo.ChildNodeGuids));
|
||||
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position));
|
||||
}
|
||||
else
|
||||
@@ -331,7 +342,7 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
}
|
||||
// 加载区域的子项
|
||||
foreach((NodeModelBase region, string[] childNodeGuids) item in regionChildNodes)
|
||||
foreach ((NodeModelBase region, string[] childNodeGuids) item in regionChildNodes)
|
||||
{
|
||||
foreach (var childNodeGuid in item.childNodeGuids)
|
||||
{
|
||||
@@ -438,8 +449,8 @@ namespace Serein.NodeFlow
|
||||
var nodeModel = CreateNode(nodeControlType, methodDetails);
|
||||
TryAddNode(nodeModel);
|
||||
|
||||
if(flowStarter?.FlowState != RunState.Completion
|
||||
&& nodeControlType == NodeControlType.Flipflop
|
||||
if (flowStarter?.FlowState != RunState.Completion
|
||||
&& nodeControlType == NodeControlType.Flipflop
|
||||
&& nodeModel is SingleFlipflopNode flipflopNode)
|
||||
{
|
||||
// 当前添加节点属于触发器,且当前正在运行,则加载到运行环境中
|
||||
@@ -553,9 +564,9 @@ namespace Serein.NodeFlow
|
||||
{
|
||||
fromNode.SuccessorNodes[connectionType].Remove(toNode);
|
||||
toNode.PreviousNodes[connectionType].Remove(fromNode);
|
||||
if(toNode is SingleFlipflopNode flipflopNode)
|
||||
if (toNode is SingleFlipflopNode flipflopNode)
|
||||
{
|
||||
if (flowStarter?.FlowState != RunState.Completion
|
||||
if (flowStarter?.FlowState != RunState.Completion
|
||||
&& flipflopNode.NotExitPreviousNode())
|
||||
{
|
||||
// 被父节点移除连接关系的子节点若为触发器,且无上级节点,则当前流程正在运行,则加载到运行环境中
|
||||
@@ -586,7 +597,7 @@ namespace Serein.NodeFlow
|
||||
md = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -618,7 +629,7 @@ namespace Serein.NodeFlow
|
||||
else if (interruptClass == InterruptClass.Branch)
|
||||
{
|
||||
nodeModel.DebugSetting.CancelInterruptCallback?.Invoke();
|
||||
nodeModel.DebugSetting.GetInterruptTask = () =>
|
||||
nodeModel.DebugSetting.GetInterruptTask = () =>
|
||||
{
|
||||
TriggerInterrupt(nodeGuid, "", InterruptTriggerEventArgs.InterruptTriggerType.Monitor);
|
||||
return ChannelFlowInterrupt.GetOrCreateChannelAsync(nodeGuid);
|
||||
@@ -627,7 +638,7 @@ namespace Serein.NodeFlow
|
||||
{
|
||||
ChannelFlowInterrupt.TriggerSignal(nodeGuid);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
else if (interruptClass == InterruptClass.Global) // 全局……做不了omg
|
||||
{
|
||||
@@ -645,66 +656,130 @@ namespace Serein.NodeFlow
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="expression"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddInterruptExpression(string nodeGuid, string expression)
|
||||
public bool AddInterruptExpression(object obj, string expression)
|
||||
{
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
if (nodeModel is null) return false;
|
||||
if (string.IsNullOrEmpty(expression))
|
||||
if (dictMonitorObjExpInterrupt.TryGetValue(obj, out var condition))
|
||||
{
|
||||
nodeModel.DebugSetting.InterruptExpressions.Clear();// 暂时删除,等UI做好了
|
||||
condition.Clear(); // 暂时
|
||||
condition.Add(expression);// 暂时
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nodeModel.DebugSetting.InterruptExpressions.Contains(expression))
|
||||
{
|
||||
Console.WriteLine("表达式已存在");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeModel.DebugSetting.InterruptExpressions.Clear();// 暂时删除,等UI做好了
|
||||
nodeModel.DebugSetting.InterruptExpressions.Add(expression);
|
||||
var exps = new List<string>();
|
||||
exps.Add(expression);
|
||||
dictMonitorObjExpInterrupt.TryAdd(obj, exps);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//public bool AddInterruptExpression(string nodeGuid, string expression)
|
||||
//{
|
||||
// var nodeModel = GuidToModel(nodeGuid);
|
||||
// if (nodeModel is null) return false;
|
||||
// if (string.IsNullOrEmpty(expression))
|
||||
// {
|
||||
// nodeModel.DebugSetting.InterruptExpressions.Clear(); // 传入空表达式时清空
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if (nodeModel.DebugSetting.InterruptExpressions.Contains(expression))
|
||||
// {
|
||||
// Console.WriteLine("表达式已存在");
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// nodeModel.DebugSetting.InterruptExpressions.Clear();// 暂时删除,等UI做好了
|
||||
// nodeModel.DebugSetting.InterruptExpressions.Add(expression);
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 监视节点的数据
|
||||
/// 监视节点的数据(暂时注释)
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">需要监视的节点Guid</param>
|
||||
public void SetNodeFLowDataMonitorState(string nodeGuid, bool isMonitor)
|
||||
{
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
if (nodeModel is null) return;
|
||||
nodeModel.DebugSetting.IsMonitorFlowData = isMonitor;
|
||||
|
||||
if (isMonitor)
|
||||
{
|
||||
var obj = nodeModel.GetFlowData();
|
||||
if(obj is not null)
|
||||
{
|
||||
FlowDataNotification(nodeGuid, obj);
|
||||
//public void SetMonitorObjState(string nodeGuid, bool isMonitor)
|
||||
//{
|
||||
// var nodeModel = GuidToModel(nodeGuid);
|
||||
// if (nodeModel is null) return;
|
||||
// nodeModel.DebugSetting.IsMonitorFlowData = isMonitor;
|
||||
|
||||
// if (isMonitor)
|
||||
// {
|
||||
// var obj = nodeModel.GetFlowData();
|
||||
// if(obj is not null)
|
||||
// {
|
||||
// FlowDataNotification(nodeGuid, obj);
|
||||
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 不再监视的节点清空表达式
|
||||
// nodeModel.DebugSetting.InterruptExpressions.Clear();
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 要监视的对象,以及与其关联的表达式
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<object, List<string>> dictMonitorObjExpInterrupt = [];
|
||||
|
||||
/// <summary>
|
||||
/// 设置对象的监视状态
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="isMonitor"></param>
|
||||
/// <returns></returns>
|
||||
public void SetMonitorObjState(object obj, bool isMonitor)
|
||||
{
|
||||
if (obj is null) { return; }
|
||||
var isExist = dictMonitorObjExpInterrupt.ContainsKey(obj);
|
||||
if (isExist)
|
||||
{
|
||||
if (!isMonitor) // 对象存在且需要不监视
|
||||
{
|
||||
dictMonitorObjExpInterrupt.Remove(obj, out _);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isMonitor) // 对象不存在且需要监视,添加在集合中。
|
||||
{
|
||||
dictMonitorObjExpInterrupt.TryAdd(obj, new List<string>()); ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节点数据更新通知
|
||||
/// 检查一个对象是否处于监听状态,如果是,则传出与该对象相关的表达式(用于中断),如果不是,则返回false。
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public void FlowDataNotification(string nodeGuid, object flowData)
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public bool CheckObjMonitorState(object obj, out List<string>? exps)
|
||||
{
|
||||
OnMonitorObjectChange?.Invoke(new MonitorObjectEventArgs(nodeGuid, flowData));
|
||||
if (obj is null) { exps = null; return false; }
|
||||
return dictMonitorObjExpInterrupt.TryGetValue(obj, out exps);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// 启动器调用,节点数据更新通知
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
|
||||
{
|
||||
OnMonitorObjectChange?.Invoke(new MonitorObjectEventArgs(nodeGuid, monitorData, sourceType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动器调用,节点触发了中断。
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点</param>
|
||||
/// <param name="expression">表达式</param>
|
||||
/// <param name="type">类型,0节点,1表达式</param>
|
||||
/// <param name="type">类型,0用户主动的中断,1表达式中断</param>
|
||||
public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type)
|
||||
{
|
||||
OnInterruptTrigger?.Invoke(new InterruptTriggerEventArgs(nodeGuid, expression, type));
|
||||
@@ -719,16 +794,6 @@ namespace Serein.NodeFlow
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid 转 NodeModel
|
||||
/// </summary>
|
||||
@@ -796,13 +861,37 @@ namespace Serein.NodeFlow
|
||||
return (null, []);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 运行环节加载了项目文件,需要创建节点控件
|
||||
/// </summary>
|
||||
/// <param name="nodeInfo"></param>
|
||||
/// <param name="methodDetailss"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private NodeControlType GetNodeControlType(NodeInfo nodeInfo)
|
||||
{
|
||||
// 创建控件实例
|
||||
NodeControlType controlType = nodeInfo.Type switch
|
||||
{
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleActionNode)}" => NodeControlType.Action,// 动作节点控件
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleFlipflopNode)}" => NodeControlType.Flipflop, // 触发器节点控件
|
||||
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleConditionNode)}" => NodeControlType.ExpCondition,// 条件表达式控件
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleExpOpNode)}" => NodeControlType.ExpOp, // 操作表达式控件
|
||||
|
||||
$"{NodeStaticConfig.NodeSpaceName}.{nameof(CompositeConditionNode)}" => NodeControlType.ConditionRegion, // 条件区域控件
|
||||
_ => NodeControlType.None,
|
||||
};
|
||||
|
||||
return controlType;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建节点
|
||||
/// </summary>
|
||||
/// <param name="nodeBase"></param>
|
||||
private NodeModelBase CreateNode(NodeControlType nodeControlType,MethodDetails? methodDetails = null)
|
||||
private NodeModelBase CreateNode(NodeControlType nodeControlType, MethodDetails? methodDetails = null)
|
||||
{
|
||||
// 确定创建的节点类型
|
||||
Type? nodeType = nodeControlType switch
|
||||
@@ -929,13 +1018,127 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 网络交互
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region IOC容器相关
|
||||
ISereinIOC ISereinIOC.Reset()
|
||||
{
|
||||
sereinIOC.Reset();
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Register(Type type, params object[] parameters)
|
||||
{
|
||||
sereinIOC.Register(type, parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Register<T>(params object[] parameters)
|
||||
{
|
||||
sereinIOC.Register<T>(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Register<TService, TImplementation>(params object[] parameters)
|
||||
{
|
||||
sereinIOC.Register<TService, TImplementation>(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
T ISereinIOC.GetOrRegisterInstantiate<T>()
|
||||
{
|
||||
return sereinIOC.GetOrRegisterInstantiate<T>();
|
||||
|
||||
}
|
||||
|
||||
object ISereinIOC.GetOrRegisterInstantiate(Type type)
|
||||
{
|
||||
return sereinIOC.GetOrRegisterInstantiate(type);
|
||||
}
|
||||
|
||||
object ISereinIOC.Get(Type type)
|
||||
{
|
||||
return sereinIOC.Get(type);
|
||||
|
||||
}
|
||||
|
||||
T ISereinIOC.Get<T>(string key)
|
||||
{
|
||||
return sereinIOC.Get<T>(key);
|
||||
}
|
||||
|
||||
void ISereinIOC.CustomRegisterInstance(string key, object instance, bool needInjectProperty)
|
||||
{
|
||||
sereinIOC.CustomRegisterInstance(key, instance, needInjectProperty);
|
||||
}
|
||||
|
||||
object ISereinIOC.Instantiate(Type type, params object[] parameters)
|
||||
{
|
||||
return sereinIOC.Instantiate(type, parameters);
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Build()
|
||||
{
|
||||
sereinIOC.Build();
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T>(Action<T> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2>(Action<T1, T2> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3>(Action<T1, T2, T3> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4, T5, T6, T7>(Action<T1, T2, T3, T4, T5, T6, T7> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4, T5, T6, T7, T8>(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
public static class FlowFunc
|
||||
{
|
||||
@@ -961,7 +1164,7 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
|
||||
|
||||
public static Type? ControlTypeToModel(this NodeControlType nodeControlType )
|
||||
public static Type? ControlTypeToModel(this NodeControlType nodeControlType)
|
||||
{
|
||||
// 确定创建的节点类型
|
||||
Type? nodeType = nodeControlType switch
|
||||
@@ -1000,7 +1203,7 @@ namespace Serein.NodeFlow
|
||||
ConnectionType.Upstream];
|
||||
foreach (ConnectionType ctType in ct)
|
||||
{
|
||||
if(node.PreviousNodes[ctType].Count > 0)
|
||||
if (node.PreviousNodes[ctType].Count > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,13 @@ namespace Serein.NodeFlow
|
||||
/// <param name="methodDetails"></param>
|
||||
public class FlowStarter
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局触发器CTS
|
||||
/// </summary>
|
||||
public const string FlipFlopCtsName = "<>.FlowFlipFlopCts";
|
||||
|
||||
public FlowStarter()
|
||||
{
|
||||
SereinIOC = new SereinIOC();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -44,22 +48,25 @@ namespace Serein.NodeFlow
|
||||
/// </summary>
|
||||
Completion,
|
||||
}
|
||||
/// <summary>
|
||||
/// 起点流程运行状态
|
||||
/// </summary>
|
||||
public RunState FlowState { get; private set; } = RunState.NoStart;
|
||||
/// <summary>
|
||||
/// 全局触发器运行状态
|
||||
/// </summary>
|
||||
public RunState FlipFlopState { get; private set; } = RunState.NoStart;
|
||||
|
||||
/// <summary>
|
||||
/// 控制触发器
|
||||
/// </summary>
|
||||
private CancellationTokenSource _flipFlopCts = null;
|
||||
public const string FlipFlopCtsName = "<>.FlowFlipFlopCts";
|
||||
|
||||
/// <summary>
|
||||
/// 是否停止启动
|
||||
/// </summary>
|
||||
private bool IsStopStart = false;
|
||||
|
||||
public bool IsStopStart = false;
|
||||
/// <summary>
|
||||
/// 运行状态
|
||||
/// </summary>
|
||||
public RunState FlowState { get; private set; } = RunState.NoStart;
|
||||
public RunState FlipFlopState { get; private set; } = RunState.NoStart;
|
||||
/// <summary>
|
||||
/// 运行时的IOC容器
|
||||
/// </summary>
|
||||
private ISereinIOC SereinIOC { get; } = null;
|
||||
/// <summary>
|
||||
/// 结束运行时需要执行的方法
|
||||
/// </summary>
|
||||
@@ -77,15 +84,17 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从选定的节点开始运行
|
||||
/// </summary>
|
||||
/// <param name="startNode"></param>
|
||||
/// <returns></returns>
|
||||
public async Task StartFlowInSelectNodeAsync(NodeModelBase startNode)
|
||||
{
|
||||
if (Context is null) return;
|
||||
await startNode.StartExecute(Context); // 开始运行时从选定节点开始运行
|
||||
}
|
||||
|
||||
// <summary>
|
||||
// 开始运行
|
||||
// </summary>
|
||||
// <param name="startNode">起始节点</param>
|
||||
// <param name="env">运行环境</param>
|
||||
// <param name="runNodeMd">环境中已加载的所有节点方法</param>
|
||||
// <param name="flipflopNodes">触发器节点</param>
|
||||
// <returns></returns>
|
||||
|
||||
/// <summary>
|
||||
/// 开始运行
|
||||
@@ -130,11 +139,11 @@ namespace Serein.NodeFlow
|
||||
var isNetFramework = false;
|
||||
if (isNetFramework)
|
||||
{
|
||||
Context = new Serein.Library.Framework.NodeFlow.DynamicContext(SereinIOC, env);
|
||||
Context = new Serein.Library.Framework.NodeFlow.DynamicContext(env);
|
||||
}
|
||||
else
|
||||
{
|
||||
Context = new Serein.Library.Core.NodeFlow.DynamicContext(SereinIOC, env); // 从起始节点启动流程时创建上下文
|
||||
Context = new Serein.Library.Core.NodeFlow.DynamicContext(env); // 从起始节点启动流程时创建上下文
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -151,13 +160,14 @@ namespace Serein.NodeFlow
|
||||
{
|
||||
nodeMd.ActingInstance = null;
|
||||
}
|
||||
SereinIOC.Reset(); // 开始运行时清空ioc中注册的实例
|
||||
env.IOC.Reset(); // 开始运行时清空ioc中注册的实例
|
||||
env.IOC.CustomRegisterInstance(typeof(ISereinIOC).FullName, env);
|
||||
// 初始化ioc容器中的类型对象
|
||||
foreach (var md in thisRuningMds)
|
||||
{
|
||||
if (md.ActingInstanceType != null)
|
||||
{
|
||||
SereinIOC.Register(md.ActingInstanceType);
|
||||
env.IOC.Register(md.ActingInstanceType);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -168,11 +178,11 @@ namespace Serein.NodeFlow
|
||||
CheckStartState(); // 初始化IOC后检查状态
|
||||
|
||||
|
||||
SereinIOC.Build(); // 流程启动前的初始化
|
||||
env.IOC.Build(); // 流程启动前的初始化
|
||||
|
||||
foreach (var md in thisRuningMds)
|
||||
{
|
||||
md.ActingInstance = SereinIOC.GetOrRegisterInstantiate(md.ActingInstanceType);
|
||||
md.ActingInstance = env.IOC.GetOrRegisterInstantiate(md.ActingInstanceType);
|
||||
if(md.ActingInstance is null)
|
||||
{
|
||||
await Console.Out.WriteLineAsync($"{md.MethodName} - 无法获取类型[{md.ActingInstanceType}]的实例");
|
||||
@@ -206,20 +216,20 @@ namespace Serein.NodeFlow
|
||||
{
|
||||
((Action<object, object?[]?>)md.MethodDelegate).Invoke(md.ActingInstance, [Context]);
|
||||
}
|
||||
Context.SereinIoc.Build(); // 绑定初始化时注册的类型
|
||||
Context.Env.IOC.Build(); // 绑定初始化时注册的类型
|
||||
foreach (var md in loadingMethods) // 加载
|
||||
{
|
||||
//object?[]? data = [md.ActingInstance, args];
|
||||
//md.MethodDelegate.DynamicInvoke(data);
|
||||
((Action<object, object?[]?>)md.MethodDelegate).Invoke(md.ActingInstance, [Context]);
|
||||
}
|
||||
Context.SereinIoc.Build(); // 预防有人在加载时才注册类型,再绑定一次
|
||||
Context.Env.IOC.Build(); // 预防有人在加载时才注册类型,再绑定一次
|
||||
#endregion
|
||||
|
||||
#region 设置流程退出时的回调函数
|
||||
ExitAction = () =>
|
||||
{
|
||||
SereinIOC.Run<WebServer>(web => {
|
||||
env.IOC.Run<WebServer>(web => {
|
||||
web?.Stop();
|
||||
});
|
||||
|
||||
@@ -248,7 +258,7 @@ namespace Serein.NodeFlow
|
||||
FlipFlopState = RunState.Running;
|
||||
// 如果存在需要启动的触发器,则开始启动
|
||||
_flipFlopCts = new CancellationTokenSource();
|
||||
SereinIOC.CustomRegisterInstance(FlipFlopCtsName, _flipFlopCts,false);
|
||||
env.IOC.CustomRegisterInstance(FlipFlopCtsName, _flipFlopCts,false);
|
||||
|
||||
// 使用 TaskCompletionSource 创建未启动的触发器任务
|
||||
var tasks = flipflopNodes.Select(async node =>
|
||||
@@ -270,7 +280,6 @@ namespace Serein.NodeFlow
|
||||
catch (Exception ex)
|
||||
{
|
||||
await Console.Out.WriteLineAsync(ex.ToString());
|
||||
// await Console.Out.WriteLineAsync(ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -279,26 +288,26 @@ namespace Serein.NodeFlow
|
||||
#endregion
|
||||
}
|
||||
|
||||
public void AddFlipflopInRuning(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment flowEnvironment)
|
||||
public void AddFlipflopInRuning(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment env)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
// 设置对象
|
||||
singleFlipFlopNode.MethodDetails.ActingInstance = SereinIOC.GetOrRegisterInstantiate(singleFlipFlopNode.MethodDetails.ActingInstanceType);
|
||||
await FlipflopExecute(flowEnvironment,singleFlipFlopNode); // 启动触发器
|
||||
singleFlipFlopNode.MethodDetails.ActingInstance = env.IOC.GetOrRegisterInstantiate(singleFlipFlopNode.MethodDetails.ActingInstanceType);
|
||||
await FlipflopExecute(env,singleFlipFlopNode); // 启动触发器
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动全局触发器
|
||||
/// </summary>
|
||||
/// <param name="flowEnvironment">流程运行全局环境</param>
|
||||
/// <param name="env">流程运行全局环境</param>
|
||||
/// <param name="singleFlipFlopNode">需要全局监听信号的触发器</param>
|
||||
/// <returns></returns>
|
||||
private async Task FlipflopExecute(IFlowEnvironment flowEnvironment,SingleFlipflopNode singleFlipFlopNode)
|
||||
private async Task FlipflopExecute(IFlowEnvironment env,SingleFlipflopNode singleFlipFlopNode)
|
||||
{
|
||||
|
||||
var context = new DynamicContext(SereinIOC, flowEnvironment); // 启动全局触发器时新建上下文
|
||||
var context = new DynamicContext(env); // 启动全局触发器时新建上下文
|
||||
try
|
||||
{
|
||||
|
||||
@@ -368,75 +377,6 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
|
||||
|
||||
#if false
|
||||
|
||||
/// <summary>
|
||||
/// 全局触发器开始执行相关分支
|
||||
/// </summary>
|
||||
/// <param name="context">上下文</param>
|
||||
/// <param name="singleFlipFlopNode">被触发的全局触发器</param>
|
||||
/// <param name="connectionType">分支类型</param>
|
||||
/// <returns></returns>
|
||||
public async Task GlobalFlipflopExecute(IDynamicContext context, SingleFlipflopNode singleFlipFlopNode,
|
||||
|
||||
ConnectionType connectionType, CancellationTokenSource cts)
|
||||
{
|
||||
|
||||
|
||||
bool skip = true;
|
||||
Stack<NodeModelBase> stack = new Stack<NodeModelBase>();
|
||||
stack.Push(singleFlipFlopNode);
|
||||
|
||||
|
||||
while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环
|
||||
{
|
||||
// 从栈中弹出一个节点作为当前节点进行处理
|
||||
var currentNode = stack.Pop();
|
||||
|
||||
// 设置方法执行的对象
|
||||
//if (currentNode.MethodDetails?.ActingInstance == null && currentNode.MethodDetails?.ActingInstanceType is not null)
|
||||
//{
|
||||
// currentNode.MethodDetails.ActingInstance ??= context.SereinIoc.GetOrRegisterInstantiate(currentNode.MethodDetails.ActingInstanceType);
|
||||
//}
|
||||
|
||||
// 首先执行上游分支
|
||||
var upstreamNodes = currentNode.SuccessorNodes[ConnectionType.Upstream];
|
||||
for (int i = upstreamNodes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
upstreamNodes[i].PreviousNode = currentNode;
|
||||
await upstreamNodes[i].StartExecute(context); // 执行全局触发器的上游分支
|
||||
}
|
||||
|
||||
// 当前节点是已经触发了的全局触发器,所以跳过,难道每次都要判断一次?
|
||||
if (skip)
|
||||
{
|
||||
skip = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentNode.FlowData = await currentNode.ExecutingAsync(context);
|
||||
|
||||
|
||||
if (currentNode.NextOrientation == ConnectionType.None)
|
||||
{
|
||||
break; // 不再执行
|
||||
}
|
||||
connectionType = currentNode.NextOrientation;
|
||||
}
|
||||
|
||||
// 获取下一分支
|
||||
var nextNodes = currentNode.SuccessorNodes[connectionType];
|
||||
|
||||
// 将下一个节点集合中的所有节点逆序推入栈中
|
||||
for (int i = nextNodes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
nextNodes[i].PreviousNode = currentNode;
|
||||
stack.Push(nextNodes[i]);
|
||||
}
|
||||
}}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Serein.Library.Api;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -12,5 +13,7 @@ namespace Serein.NodeFlow
|
||||
/// 节点的命名空间
|
||||
/// </summary>
|
||||
public const string NodeSpaceName = $"{nameof(Serein)}.{nameof(Serein.NodeFlow)}.{nameof(Serein.NodeFlow.Model)}";
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user