From 162dc7bcf82b3597397d3d697e5e4e130f6b0f34 Mon Sep 17 00:00:00 2001
From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com>
Date: Fri, 4 Jul 2025 21:31:07 +0800
Subject: [PATCH] =?UTF-8?q?=E5=87=86=E5=A4=87=E6=B7=BB=E5=8A=A0=E6=B5=81?=
=?UTF-8?q?=E7=A8=8B=E6=8E=A5=E5=8F=A3=E8=B0=83=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Library/Api/IEmbeddedContent.cs | 4 +-
Library/Api/IFlowControl.cs | 68 +
Library/Api/IFlowEdit.cs | 169 +++
Library/Api/IFlowEnvironment.cs | 354 ++----
Library/Extension/FlowModelExtension.cs | 63 +-
Library/FlowNode/FlowResult.cs | 9 +-
NodeFlow/Env/FlowControl.cs | 375 ++++++
NodeFlow/Env/FlowEdit.cs | 568 +++++++++
NodeFlow/Env/FlowEnvironment.cs | 276 +----
NodeFlow/Env/LocalFlowEnvironment.cs | 1100 +----------------
NodeFlow/FlowNodeExtension.cs | 2 +-
NodeFlow/Model/Node/NodeModelBaseFunc.cs | 2 +-
NodeFlow/Model/Node/SingleFlowCallNode.cs | 8 +-
NodeFlow/Model/Node/SingleGlobalDataNode.cs | 2 +-
.../Model/Operation/CreateNodeOperation.cs | 2 +-
NodeFlow/Services/FlowApiService.cs | 27 -
.../Node/Junction/JunctionControlBase.cs | 4 +-
Workbench/Node/View/ConnectionControl.cs | 6 +-
Workbench/Services/FlowNodeService.cs | 30 +-
.../Themes/NodeTreeItemViewControl.xaml.cs | 4 +-
Workbench/ViewModels/MainMenuBarViewModel.cs | 4 +-
Workbench/Views/FlowCanvasView.xaml.cs | 20 +-
Workbench/Views/ViewCanvasInfoView.xaml.cs | 2 +-
23 files changed, 1401 insertions(+), 1698 deletions(-)
create mode 100644 Library/Api/IFlowControl.cs
create mode 100644 Library/Api/IFlowEdit.cs
create mode 100644 NodeFlow/Env/FlowControl.cs
create mode 100644 NodeFlow/Env/FlowEdit.cs
diff --git a/Library/Api/IEmbeddedContent.cs b/Library/Api/IEmbeddedContent.cs
index bf1eb6b..7f8b54b 100644
--- a/Library/Api/IEmbeddedContent.cs
+++ b/Library/Api/IEmbeddedContent.cs
@@ -10,7 +10,7 @@ namespace Serein.Library.Api
///
/// 流程中的控件
///
- public interface IFlowControl
+ public interface IFlowUIControl
{
///
/// 节点执行事件
@@ -33,7 +33,7 @@ namespace Serein.Library.Api
/// 获取窗体控件
///
///
- IFlowControl GetFlowControl();
+ IFlowUIControl GetFlowControl();
}
diff --git a/Library/Api/IFlowControl.cs b/Library/Api/IFlowControl.cs
new file mode 100644
index 0000000..36df475
--- /dev/null
+++ b/Library/Api/IFlowControl.cs
@@ -0,0 +1,68 @@
+using System.Threading.Tasks;
+
+namespace Serein.Library.Api
+{
+ ///
+ /// 流程运行接口
+ ///
+ public interface IFlowControl
+ {
+ ///
+ /// 需要你提供一个由你实现的ISereinIOC接口实现类
+ /// 当你将流程运行环境集成在你的项目时,并希望流程运行时使用你提供的对象,而非自动创建
+ /// 就需要你调用这个方法,用来替换运行环境的IOC容器
+ /// 注意,是流程运行时,而非运行环境
+ ///
+ ///
+ void UseExternalIOC(ISereinIOC ioc);
+
+ ///
+ /// 开始运行流程
+ ///
+ /// 需要运行的流程Guid
+ ///
+ Task StartFlowAsync(string[] canvasGuids);
+
+ ///
+ /// 从选定的节点开始运行
+ ///
+ ///
+ ///
+ Task StartFlowFromSelectNodeAsync(string startNodeGuid);
+
+ ///
+ /// 结束运行
+ ///
+ Task ExitFlowAsync();
+
+ ///
+ /// 激活未启动的全局触发器
+ ///
+ ///
+ void ActivateFlipflopNode(string nodeGuid);
+
+ ///
+ /// 终结一个全局触发器,在它触发后将不会再次监听消息(表现为已经启动的触发器至少会再次处理一次消息,后面版本再修正这个非预期行为)
+ ///
+ ///
+ void TerminateFlipflopNode(string nodeGuid);
+
+ ///
+ /// 流程启动器调用,监视数据更新通知
+ ///
+ /// 更新了数据的节点Guid
+ /// 更新的数据
+ /// 更新的数据
+ void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType);
+
+ ///
+ /// 流程启动器调用,节点触发了中断
+ ///
+ /// 被中断的节点Guid
+ /// 被触发的表达式
+ /// 中断类型。0主动监视,1表达式
+ void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type);
+ }
+
+
+}
diff --git a/Library/Api/IFlowEdit.cs b/Library/Api/IFlowEdit.cs
new file mode 100644
index 0000000..e848a65
--- /dev/null
+++ b/Library/Api/IFlowEdit.cs
@@ -0,0 +1,169 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Serein.Library.Api
+{
+ ///
+ /// 流程编辑
+ ///
+ public interface IFlowEdit
+ {
+
+ ///
+ /// 节点视图模型管理类
+ ///
+ NodeMVVMService NodeMVVMManagement { get; }
+
+ ///
+ /// 从节点信息集合批量加载节点控件
+ ///
+ /// 节点集合信息
+ ///
+ Task LoadNodeInfosAsync(List nodeInfos);
+
+ #region 流程节点操作接口
+
+ ///
+ /// 增加画布
+ ///
+ /// 画布名称
+ /// 宽度
+ /// 高度
+ ///
+ void CreateCanvas(string canvasName, int width, int height);
+
+ ///
+ /// 删除画布
+ ///
+ /// 画布Guid
+ ///
+ void RemoveCanvas(string canvasGuid);
+
+
+
+
+ ///
+ /// 在两个节点之间创建连接关系
+ ///
+ /// 所在画布
+ /// 起始节点Guid
+ /// 目标节点Guid
+ /// 起始节点控制点
+ /// 目标节点控制点
+ /// 决定了方法执行后的后继行为
+ void ConnectInvokeNode(string canvasGuid,
+ string fromNodeGuid,
+ string toNodeGuid,
+ JunctionType fromNodeJunctionType,
+ JunctionType toNodeJunctionType,
+ ConnectionInvokeType invokeType);
+
+ ///
+ /// 在两个节点之间创建连接关系
+ ///
+ /// 所在画布
+ /// 起始节点Guid
+ /// 目标节点Guid
+ /// 起始节点控制点
+ /// 目标节点控制点
+ /// 决定了方法参数来源
+ /// 设置第几个参数
+ void ConnectArgSourceNode(string canvasGuid,
+ string fromNodeGuid,
+ string toNodeGuid,
+ JunctionType fromNodeJunctionType,
+ JunctionType toNodeJunctionType,
+ ConnectionArgSourceType argSourceType,
+ int argIndex);
+
+ ///
+ /// 移除两个节点之间的方法调用关系
+ ///
+ /// 所在画布
+ /// 起始节点
+ /// 目标节点
+ /// 连接类型
+ void RemoveInvokeConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType);
+
+ ///
+ /// 移除连接节点之间参数传递的关系
+ ///
+ /// 所在画布
+ /// 起始节点Guid
+ /// 目标节点Guid
+ /// 连接到第几个参数
+ void RemoveArgSourceConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, int argIndex);
+
+
+ ///
+ /// 创建节点
+ ///
+ /// 所在画布
+ /// 控件类型
+ /// 节点在画布上的位置(
+ /// 节点绑定的方法说明
+ void CreateNode(string canvasGuid, NodeControlType nodeType, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null);
+
+ ///
+ /// 移除节点
+ ///
+ /// 所在画布
+ /// 待移除的节点Guid
+ void RemoveNode(string canvasGuid, string nodeGuid);
+
+ ///
+ /// 将节点放置在容器中
+ ///
+ /// 所在画布
+ /// 需要放置的节点Guid
+ /// 存放节点的容器Guid
+ ///
+ void PlaceNodeToContainer(string canvasGuid, string nodeGuid, string containerNodeGuid);
+
+ ///
+ /// 将节点放置在容器中
+ ///
+ /// 所在画布
+ /// 需要取出的节点Guid
+ void TakeOutNodeToContainer(string canvasGuid, string nodeGuid);
+
+ ///
+ /// 设置流程起点节点
+ ///
+ /// 所在画布
+ /// 尝试设置为起始节点的节点Guid
+ /// 被设置为起始节点的Guid
+ void SetStartNode(string canvasGuid, string nodeGuid);
+
+ ///
+ /// 设置两个节点某个类型的方法调用关系为优先调用
+ ///
+ /// 起始节点
+ /// 目标节点
+ /// 连接关系
+ ///
+ void SetConnectPriorityInvoke(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType);
+
+
+ ///
+ /// 改变可选参数的数目
+ ///
+ /// 对应的节点Guid
+ /// true,增加参数;false,减少参数
+ /// 以哪个参数为模板进行拷贝,或删去某个参数(该参数必须为可选参数)
+ ///
+ void ChangeParameter(string nodeGuid, bool isAdd, int paramIndex);
+
+ #endregion
+
+ #region UI视觉
+
+ ///
+ /// 节点定位
+ ///
+ ///
+ void NodeLocate(string nodeGuid);
+
+ #endregion
+ }
+}
diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs
index 40c485d..7962d87 100644
--- a/Library/Api/IFlowEnvironment.cs
+++ b/Library/Api/IFlowEnvironment.cs
@@ -748,7 +748,7 @@ namespace Serein.Library.Api
public void OnEnvOutput(InfoType type, string value);
}
-
+
///
/// 运行环境
@@ -764,6 +764,15 @@ namespace Serein.Library.Api
///
ISereinIOC IOC { get; }
+ ///
+ /// 流程编辑接口
+ ///
+ IFlowEdit FlowEdit { get; }
+
+ ///
+ /// 流程控制接口
+ ///
+ IFlowControl FlowControl { get; }
///
/// 流程事件接口
@@ -811,10 +820,6 @@ namespace Serein.Library.Api
///
UIContextOperation UIContextOperation { get; }
- ///
- /// 节点视图模型管理类
- ///
- NodeMVVMService NodeMVVMManagement { get; }
#endregion
#region 基本接口
@@ -826,6 +831,17 @@ namespace Serein.Library.Api
/// 输出类型
/// 输出级别
void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial);
+ ///
+ /// 提供设置UI上下文的能力
+ /// 提供设置UI上下文的能力,在WinForm/WPF项目中,在UI线程外对UI元素的修改将会导致异常
+ /// 需要你提供
+ ///
+ ///
+ void SetUIContextOperation(UIContextOperation uiContextOperation);
+ #endregion
+
+
+ #region 项目相关操作
///
/// 加载项目文件
@@ -845,15 +861,69 @@ namespace Serein.Library.Api
///
Task GetProjectInfoAsync();
+ #endregion
+
+ #region 获取节点信息,获取方法信息,获取Emit委托
///
- /// 从节点信息集合批量加载节点控件
+ /// 获取节点信息
///
- /// 节点集合信息
+ ///
+ ///
///
- Task LoadNodeInfosAsync(List nodeInfos);
+ bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel);
+
+ ///
+ /// 获取方法描述信息
+ ///
+ /// 程序集名称
+ /// 方法描述
+ /// 方法信息
+ ///
+ bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo mdInfo);
+
+ ///
+ /// 获取指定方法的Emit委托
+ ///
+ /// 程序集名称
+ ///
+ ///
+ ///
+ bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del);
+ #endregion
+
+
+ #region 类库依赖相关
+
+ ///
+ /// 从文件中加载Dll
+ ///
+ ///
+ void LoadLibrary(string dllPath);
+
+ ///
+ /// 移除DLL
+ ///
+ /// 程序集的名称
+ bool TryUnloadLibrary(string assemblyFullName);
+
+ ///
+ /// 运行时加载
+ ///
+ /// 文件名
+ ///
+ bool LoadNativeLibraryOfRuning(string file);
+
+ ///
+ /// 运行时加载指定目录下的类库
+ ///
+ /// 目录
+ /// 是否递归加载
+ void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true);
#endregion
+
+
#region 远程相关
///
/// 启动远程服务
@@ -895,142 +965,9 @@ namespace Serein.Library.Api
#endregion
- #region 流程节点操作接口
-
- ///
- /// 增加画布
- ///
- /// 画布名称
- /// 宽度
- /// 高度
- ///
- void CreateCanvas(string canvasName, int width , int height);
-
- ///
- /// 删除画布
- ///
- /// 画布Guid
- ///
- void RemoveCanvas(string canvasGuid);
-
-
- ///
- /// 在两个节点之间创建连接关系
- ///
- /// 所在画布
- /// 起始节点Guid
- /// 目标节点Guid
- /// 起始节点控制点
- /// 目标节点控制点
- /// 决定了方法执行后的后继行为
- void ConnectInvokeNode(string canvasGuid,
- string fromNodeGuid,
- string toNodeGuid,
- JunctionType fromNodeJunctionType,
- JunctionType toNodeJunctionType,
- ConnectionInvokeType invokeType);
-
- ///
- /// 在两个节点之间创建连接关系
- ///
- /// 所在画布
- /// 起始节点Guid
- /// 目标节点Guid
- /// 起始节点控制点
- /// 目标节点控制点
- /// 决定了方法参数来源
- /// 设置第几个参数
- void ConnectArgSourceNode(string canvasGuid,
- string fromNodeGuid,
- string toNodeGuid,
- JunctionType fromNodeJunctionType,
- JunctionType toNodeJunctionType,
- ConnectionArgSourceType argSourceType,
- int argIndex);
-
- ///
- /// 移除两个节点之间的方法调用关系
- ///
- /// 所在画布
- /// 起始节点
- /// 目标节点
- /// 连接类型
- void RemoveInvokeConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType);
-
- ///
- /// 移除连接节点之间参数传递的关系
- ///
- /// 所在画布
- /// 起始节点Guid
- /// 目标节点Guid
- /// 连接到第几个参数
- void RemoveArgSourceConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, int argIndex);
-
-
- ///
- /// 创建节点
- ///
- /// 所在画布
- /// 控件类型
- /// 节点在画布上的位置(
- /// 节点绑定的方法说明
- void CreateNode(string canvasGuid, NodeControlType nodeType, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null);
-
- ///
- /// 移除节点
- ///
- /// 所在画布
- /// 待移除的节点Guid
- void RemoveNode(string canvasGuid, string nodeGuid);
-
- ///
- /// 将节点放置在容器中
- ///
- /// 所在画布
- /// 需要放置的节点Guid
- /// 存放节点的容器Guid
- ///
- void PlaceNodeToContainer(string canvasGuid, string nodeGuid, string containerNodeGuid);
-
- ///
- /// 将节点放置在容器中
- ///
- /// 所在画布
- /// 需要取出的节点Guid
- void TakeOutNodeToContainer(string canvasGuid, string nodeGuid);
-
- ///
- /// 设置流程起点节点
- ///
- /// 所在画布
- /// 尝试设置为起始节点的节点Guid
- /// 被设置为起始节点的Guid
- void SetStartNode(string canvasGuid, string nodeGuid);
-
- ///
- /// 设置两个节点某个类型的方法调用关系为优先调用
- ///
- /// 起始节点
- /// 目标节点
- /// 连接关系
- ///
- void SetConnectPriorityInvoke(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType);
-
-
- ///
- /// 改变可选参数的数目
- ///
- /// 对应的节点Guid
- /// true,增加参数;false,减少参数
- /// 以哪个参数为模板进行拷贝,或删去某个参数(该参数必须为可选参数)
- ///
- void ChangeParameter(string nodeGuid, bool isAdd, int paramIndex);
-
- #endregion
-
- #region 节点中断、表达式
+ #region 节点中断、表达式(暂时没用)
#if false
///
@@ -1074,137 +1011,8 @@ namespace Serein.Library.Api
#endif
#endregion
- #region 流程运行相关
- ///
- /// 获取节点信息
- ///
- ///
- ///
- ///
- bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel);
- ///
- /// 获取方法描述信息
- ///
- /// 程序集名称
- /// 方法描述
- /// 方法信息
- ///
- bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo mdInfo);
-
- ///
- /// 获取指定方法的Emit委托
- ///
- /// 程序集名称
- ///
- ///
- ///
- bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del);
-
- ///
- /// 提供设置UI上下文的能力
- /// 提供设置UI上下文的能力,在WinForm/WPF项目中,在UI线程外对UI元素的修改将会导致异常
- /// 需要你提供
- ///
- ///
- void SetUIContextOperation(UIContextOperation uiContextOperation);
-
- ///
- /// 需要你提供一个由你实现的ISereinIOC接口实现类
- /// 当你将流程运行环境集成在你的项目时,并希望流程运行时使用你提供的对象,而非自动创建
- /// 就需要你调用这个方法,用来替换运行环境的IOC容器
- /// 注意,是流程运行时,而非运行环境
- ///
- ///
- void UseExternalIOC(ISereinIOC ioc);
-
- ///
- /// 开始运行流程
- ///
- /// 需要运行的流程Guid
- ///
- Task StartFlowAsync(string[] canvasGuids);
-
- ///
- /// 从选定的节点开始运行
- ///
- ///
- ///
- Task StartFlowFromSelectNodeAsync(string startNodeGuid);
-
- ///
- /// 结束运行
- ///
- Task ExitFlowAsync();
-
- ///
- /// 激活未启动的全局触发器
- ///
- ///
- void ActivateFlipflopNode(string nodeGuid);
-
- ///
- /// 终结一个全局触发器,在它触发后将不会再次监听消息(表现为已经启动的触发器至少会再次处理一次消息,后面版本再修正这个非预期行为)
- ///
- ///
- void TerminateFlipflopNode(string nodeGuid);
-
- ///
- /// 流程启动器调用,监视数据更新通知
- ///
- /// 更新了数据的节点Guid
- /// 更新的数据
- /// 更新的数据
- void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType);
-
- ///
- /// 流程启动器调用,节点触发了中断
- ///
- /// 被中断的节点Guid
- /// 被触发的表达式
- /// 中断类型。0主动监视,1表达式
- void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type);
-
- #endregion
-
- #region 类库依赖相关
-
- ///
- /// 从文件中加载Dll
- ///
- ///
- void LoadLibrary(string dllPath);
-
- ///
- /// 移除DLL
- ///
- /// 程序集的名称
- bool TryUnloadLibrary(string assemblyFullName);
-
- ///
- /// 运行时加载
- ///
- /// 文件名
- ///
- bool LoadNativeLibraryOfRuning(string file);
-
- ///
- /// 运行时加载指定目录下的类库
- ///
- /// 目录
- /// 是否递归加载
- void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true);
-
- #endregion
-
- #region UI视觉
-
- ///
- /// 节点定位
- ///
- ///
- void NodeLocate(string nodeGuid);
-
- #endregion
}
+
+
}
diff --git a/Library/Extension/FlowModelExtension.cs b/Library/Extension/FlowModelExtension.cs
index 4e8a8d3..fa54879 100644
--- a/Library/Extension/FlowModelExtension.cs
+++ b/Library/Extension/FlowModelExtension.cs
@@ -200,25 +200,24 @@ namespace Serein.Library
///
/// 流程运行
///
- public static async Task StartFlowAsync(this IFlowNode nodeModel, IDynamicContext context, CancellationToken token)
+ public static async Task StartFlowAsync(this IFlowNode nodeModel, IDynamicContext context, CancellationToken token)
{
Stack stack = new Stack();
HashSet processedNodes = new HashSet(); // 用于记录已处理上游节点的节点
stack.Push(nodeModel);
- while (context.RunState != RunState.Completion // 没有完成
- && token.IsCancellationRequested == false // 没有取消
- && stack.Count > 0) // 循环中直到栈为空才会退出循环
+
+ while (true)
{
-#if DEBUG
- await Task.Delay(1);
-#endif
+ if (token.IsCancellationRequested)
+ {
+ throw new Exception($"流程执行被取消,未能获取到流程结果。");
+ }
#region 执行相关
// 从栈中弹出一个节点作为当前节点进行处理
var currentNode = stack.Pop();
context.NextOrientation = ConnectionInvokeType.None; // 重置上下文状态
-
- FlowResult flowResult;
+ FlowResult flowResult = null;
try
{
flowResult = await currentNode.ExecutingAsync(context, token);
@@ -230,18 +229,15 @@ namespace Serein.Library
}
catch (Exception ex)
{
- flowResult = new FlowResult(currentNode,context);
+ flowResult = new FlowResult(currentNode, context);
context.Env.WriteLine(InfoType.ERROR, $"节点[{currentNode.Guid}]异常:" + ex);
context.NextOrientation = ConnectionInvokeType.IsError;
context.ExceptionOfRuning = ex;
}
#endregion
- #region 执行完成
- //var ignodeState = context.GetIgnodeFlowStateUpload(currentNode);
- // 更新数据
- //if(!ignodeState)
- context.AddOrUpdate(currentNode, flowResult); // 上下文中更新数据
+ #region 执行完成时更新栈
+ context.AddOrUpdate(currentNode, flowResult); // 上下文中更新数据
// 首先将指定类别后继分支的所有节点逆序推入栈中
var nextNodes = currentNode.SuccessorNodes[context.NextOrientation];
@@ -255,6 +251,7 @@ namespace Serein.Library
stack.Push(nextNodes[index]);
}
}
+
// 然后将指上游分支的所有节点逆序推入栈中
var upstreamNodes = currentNode.SuccessorNodes[ConnectionInvokeType.Upstream];
for (int index = upstreamNodes.Count - 1; index >= 0; index--)
@@ -262,17 +259,40 @@ namespace Serein.Library
// 筛选出启用的节点的节点
if (upstreamNodes[index].DebugSetting.IsEnable)
{
- //if (!ignodeState)
- context.SetPreviousNode(upstreamNodes[index], currentNode);
+ context.SetPreviousNode(upstreamNodes[index], currentNode);
stack.Push(upstreamNodes[index]);
}
}
- //context.RecoverIgnodeFlowStateUpload(currentNode);
#endregion
+ #region 执行完成后检查
+
+ if (stack.Count == 0)
+ {
+ return flowResult; // 说明流程到了终点
+ }
+
+ if (context.RunState == RunState.Completion)
+ {
+ currentNode.Env.WriteLine(InfoType.INFO, $"流程执行到节点[{currentNode.Guid}]时提前结束,将返回当前执行结果。");
+ return flowResult; // 流程执行完成,返回结果
+ }
+
+ if (token.IsCancellationRequested)
+ {
+ throw new Exception($"流程执行到节点[{currentNode.Guid}]时被取消,未能获取到流程结果。");
+ }
+
+
+ #endregion
+#if DEBUG
+ await Task.Delay(1);
+#endif
}
+
}
+
///
/// 获取对应的参数数组
///
@@ -478,5 +498,12 @@ namespace Serein.Library
}
#endif
+
+
+
+
+
+
+
}
}
diff --git a/Library/FlowNode/FlowResult.cs b/Library/FlowNode/FlowResult.cs
index d847ae6..40fb360 100644
--- a/Library/FlowNode/FlowResult.cs
+++ b/Library/FlowNode/FlowResult.cs
@@ -32,10 +32,11 @@ namespace Serein.Library
///
public FlowResult(IFlowNode nodeModel, IDynamicContext context, object value)
{
- this.NodeGuid = nodeModel.Guid;
+ this.Source = nodeModel;
this.ContextGuid = context.Guid;
this.Value = value;
}
+
///
/// 空返回值
///
@@ -43,10 +44,11 @@ namespace Serein.Library
///
public FlowResult(IFlowNode nodeModel, IDynamicContext context)
{
- this.NodeGuid = nodeModel.Guid;
+ this.Source = nodeModel;
this.ContextGuid = context.Guid;
this.Value = Unit.Default;
}
+
///
/// 尝试获取值
///
@@ -74,7 +76,7 @@ namespace Serein.Library
///
/// 来源节点Guid
///
- public string NodeGuid { get; }
+ public IFlowNode Source{ get; }
///
/// 来源上下文Guid
///
@@ -83,6 +85,7 @@ namespace Serein.Library
/// 数据值
///
public object Value { get; private set; }
+
///
/// 生成时间
///
diff --git a/NodeFlow/Env/FlowControl.cs b/NodeFlow/Env/FlowControl.cs
new file mode 100644
index 0000000..4fbfe58
--- /dev/null
+++ b/NodeFlow/Env/FlowControl.cs
@@ -0,0 +1,375 @@
+using Serein.Library;
+using Serein.Library.Api;
+using Serein.Library.Utils;
+using Serein.NodeFlow.Model;
+using Serein.NodeFlow.Services;
+using Serein.NodeFlow.Tool;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxTokenParser;
+
+namespace Serein.NodeFlow.Env
+{
+
+ internal class FlowControl : IFlowControl
+ {
+ private readonly IFlowEnvironment flowEnvironment;
+ private readonly IFlowEnvironmentEvent flowEnvironmentEvent;
+ private readonly FlowLibraryService flowLibraryService;
+ private readonly FlowOperationService flowOperationService;
+ private readonly FlowModelService flowModelService;
+ private readonly UIContextOperation UIContextOperation;
+
+ public FlowControl(IFlowEnvironment flowEnvironment,
+ IFlowEnvironmentEvent flowEnvironmentEvent,
+ FlowLibraryService flowLibraryService,
+ FlowOperationService flowOperationService,
+ FlowModelService flowModelService,
+ UIContextOperation UIContextOperation)
+ {
+ this.flowEnvironment = flowEnvironment;
+ this.flowEnvironmentEvent = flowEnvironmentEvent;
+ this.flowLibraryService = flowLibraryService;
+ this.flowOperationService = flowOperationService;
+ this.flowModelService = flowModelService;
+ this.UIContextOperation = UIContextOperation;
+ contexts = new ObjectPool(() => new DynamicContext(flowEnvironment));
+ }
+
+ private ObjectPool contexts;
+ private FlowWorkManagement flowWorkManagement;
+ private ISereinIOC sereinIOC;
+
+
+ ///
+ /// 如果全局触发器还在运行,则为 Running 。
+ ///
+ private RunState FlipFlopState = RunState.NoStart;
+
+
+ ///
+ /// 异步运行
+ ///
+ ///
+ public async Task StartFlowAsync(string[] canvasGuids)
+ {
+ #region 校验参数
+ HashSet guids = new HashSet();
+ bool isBreak = false;
+ foreach (var canvasGuid in canvasGuids)
+ {
+ if (guids.Contains(canvasGuid))
+ {
+ flowEnvironment.WriteLine(InfoType.WARN, $"画布重复,停止运行。{canvasGuid}");
+ isBreak = true;
+ }
+ else if (!flowModelService.ContainsCanvasModel(canvasGuid))
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{canvasGuid}");
+ isBreak = true;
+ }
+ else if (!flowModelService.IsExsitNodeOnCanvas(canvasGuid))
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布没有节点,停止运行。{canvasGuid}");
+ isBreak = true;
+ }
+ else
+ {
+ guids.Add(canvasGuid);
+ }
+ }
+ if (isBreak)
+ {
+ guids.Clear();
+ return false;
+ }
+ #endregion
+
+
+ #region 初始化每个画布的数据,转换为流程任务
+ Dictionary flowTasks = [];
+ foreach (var guid in guids)
+ {
+ if (!flowModelService.TryGetCanvasModel(guid, out var canvasModel))
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{guid}");
+ return false;
+ }
+ var ft = new FlowTask();
+ ft.GetNodes = () => flowModelService.GetAllNodeModel(guid);
+ if (canvasModel.StartNode?.Guid is null)
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布不存在起始节点,将停止运行。{guid}");
+ return false;
+ }
+ ft.GetStartNode = () => canvasModel.StartNode;
+ flowTasks.Add(guid, ft);
+ }
+ #endregion
+
+ sereinIOC.Reset();
+ sereinIOC.Register(() => flowEnvironment);
+ sereinIOC.Register(); // 注册脚本接口
+
+ var flowTaskOptions = new FlowWorkOptions
+ {
+ Environment = flowEnvironment, // 流程
+ Flows = flowTasks,
+ FlowContextPool = contexts, // 上下文对象池
+ AutoRegisterTypes = flowLibraryService.GetaAutoRegisterType(), // 需要自动实例化的类型
+ InitMds = flowLibraryService.GetMdsOnFlowStart(NodeType.Init),
+ LoadMds = flowLibraryService.GetMdsOnFlowStart(NodeType.Loading),
+ ExitMds = flowLibraryService.GetMdsOnFlowStart(NodeType.Exit),
+ };
+
+
+
+ flowWorkManagement = new FlowWorkManagement(flowTaskOptions);
+ var cts = new CancellationTokenSource();
+ try
+ {
+ var t = await flowWorkManagement.RunAsync(cts.Token);
+ }
+ catch (Exception ex)
+ {
+ SereinEnv.WriteLine(ex);
+ }
+ finally
+ {
+
+ SereinEnv.WriteLine(InfoType.INFO, $"流程运行完毕{Environment.NewLine}"); ;
+ }
+ flowTaskOptions = null;
+ return true;
+ }
+
+
+ ///
+ /// 从选定节点开始运行
+ ///
+ ///
+ ///
+ public async Task StartFlowFromSelectNodeAsync(string startNodeGuid)
+ {
+
+ var flowTaskOptions = new FlowWorkOptions
+ {
+ Environment = flowEnvironment, // 流程
+ FlowContextPool = contexts, // 上下文对象池
+ };
+ var flowTaskManagement = new FlowWorkManagement(flowTaskOptions);
+
+ if (true || flowEnvironment.FlowState == RunState.Running || FlipFlopState == RunState.Running)
+ {
+
+ if (!flowModelService.TryGetNodeModel(startNodeGuid, out var nodeModel) || nodeModel is SingleFlipflopNode)
+ {
+ return false;
+ }
+ await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /*///
+ /// 单独运行一个节点
+ ///
+ ///
+ ///
+ public async Task
public class FlowEnvironment : IFlowEnvironment
{
+ ///
+ /// 流程运行环境构造函数
+ ///
public FlowEnvironment()
{
ISereinIOC ioc = new SereinIOC();
@@ -52,6 +55,8 @@ namespace Serein.NodeFlow.Env
.Register(()=> ioc) // 注册IOC
.Register(() => this)
.Register()
+ .Register()
+ .Register()
.Register()
.Register()
.Register()
@@ -63,7 +68,7 @@ namespace Serein.NodeFlow.Env
currentFlowEnvironmentEvent = ioc.Get();
SereinEnv.SetEnv(currentFlowEnvironment);
}
-
+/*
///
/// 本地环境事件
///
@@ -73,7 +78,7 @@ namespace Serein.NodeFlow.Env
/// 远程环境事件
///
private IFlowEnvironmentEvent remoteFlowEnvironmentEvent;
-
+ */
///
/// 管理当前环境
@@ -86,9 +91,9 @@ namespace Serein.NodeFlow.Env
///
private IFlowEnvironmentEvent currentFlowEnvironmentEvent;
+
+
private int _loadingProjectFlag = 0; // 使用原子自增代替锁
-
-
///
/// 传入false时,将停止数据通知。传入true时,
///
@@ -110,8 +115,12 @@ namespace Serein.NodeFlow.Env
public IFlowEnvironment CurrentEnv => currentFlowEnvironment;
///
public UIContextOperation UIContextOperation => currentFlowEnvironment.UIContextOperation;
+
///
- public NodeMVVMService NodeMVVMManagement => currentFlowEnvironment.NodeMVVMManagement;
+ public IFlowEdit FlowEdit => currentFlowEnvironment.FlowEdit;
+
+ ///
+ public IFlowControl FlowControl => currentFlowEnvironment.FlowControl;
///
public ISereinIOC IOC => currentFlowEnvironment.IOC;
@@ -138,172 +147,10 @@ namespace Serein.NodeFlow.Env
///
public RunState FlowState { get => currentFlowEnvironment.FlowState; set => currentFlowEnvironment.FlowState = value; }
- ///
- public event LoadDllHandler DllLoad {
- add { currentFlowEnvironmentEvent.DllLoad += value; }
- remove { currentFlowEnvironmentEvent.DllLoad -= value; }
- }
-
- ///
- public event ProjectLoadedHandler ProjectLoaded
- {
- add { currentFlowEnvironmentEvent.ProjectLoaded += value; }
- remove { currentFlowEnvironmentEvent.ProjectLoaded -= value; }
- }
-
- ///
- public event ProjectSavingHandler? ProjectSaving
- {
- add { currentFlowEnvironmentEvent.ProjectSaving += value; }
- remove { currentFlowEnvironmentEvent.ProjectSaving -= value; }
- }
-
- ///
- public event NodeConnectChangeHandler NodeConnectChanged
- {
- add { currentFlowEnvironmentEvent.NodeConnectChanged += value; }
- remove { currentFlowEnvironmentEvent.NodeConnectChanged -= value; }
- }
-
- ///
- public event CanvasCreateHandler CanvasCreated
- {
- add { currentFlowEnvironmentEvent.CanvasCreated += value; }
- remove { currentFlowEnvironmentEvent.CanvasCreated -= value; }
- }
-
- ///
- public event CanvasRemoveHandler CanvasRemoved
- {
- add { currentFlowEnvironmentEvent.CanvasRemoved += value; }
- remove { currentFlowEnvironmentEvent.CanvasRemoved -= value; }
- }
-
- ///
- public event NodeCreateHandler NodeCreated
- {
- add { currentFlowEnvironmentEvent.NodeCreated += value; }
- remove { currentFlowEnvironmentEvent.NodeCreated -= value; }
- }
-
- ///
- public event NodeRemoveHandler NodeRemoved
- {
- add { currentFlowEnvironmentEvent.NodeRemoved += value; }
- remove { currentFlowEnvironmentEvent.NodeRemoved -= value; }
- }
-
- ///
- public event NodePlaceHandler NodePlace
- {
- add { currentFlowEnvironmentEvent.NodePlace += value; }
- remove { currentFlowEnvironmentEvent.NodePlace -= value; }
- }
-
- ///
- public event NodeTakeOutHandler NodeTakeOut
- {
- add { currentFlowEnvironmentEvent.NodeTakeOut += value; }
- remove { currentFlowEnvironmentEvent.NodeTakeOut -= value; }
- }
-
- ///
- public event StartNodeChangeHandler StartNodeChanged
- {
- add { currentFlowEnvironmentEvent.StartNodeChanged += value; }
- remove { currentFlowEnvironmentEvent.StartNodeChanged -= value; }
- }
-
- ///
- public event FlowRunCompleteHandler FlowRunComplete
- {
- add { currentFlowEnvironmentEvent.FlowRunComplete += value; }
- remove { currentFlowEnvironmentEvent.FlowRunComplete -= value; }
- }
-
- ///
- public event MonitorObjectChangeHandler MonitorObjectChanged
- {
- add { currentFlowEnvironmentEvent.MonitorObjectChanged += value; }
- remove { currentFlowEnvironmentEvent.MonitorObjectChanged -= value; }
- }
-
- ///
- public event NodeInterruptStateChangeHandler NodeInterruptStateChanged
- {
- add { currentFlowEnvironmentEvent.NodeInterruptStateChanged += value; }
- remove { currentFlowEnvironmentEvent.NodeInterruptStateChanged -= value; }
- }
-
- ///
- public event ExpInterruptTriggerHandler InterruptTriggered
- {
- add { currentFlowEnvironmentEvent.InterruptTriggered += value; }
- remove { currentFlowEnvironmentEvent.InterruptTriggered -= value; }
- }
-
- ///
- public event IOCMembersChangedHandler IOCMembersChanged
- {
- add { currentFlowEnvironmentEvent.IOCMembersChanged += value; }
- remove { currentFlowEnvironmentEvent.IOCMembersChanged -= value; }
- }
-
- ///
- public event NodeLocatedHandler NodeLocated
- {
- add { currentFlowEnvironmentEvent.NodeLocated += value; }
- remove { currentFlowEnvironmentEvent.NodeLocated -= value; }
- }
-
- ///
- public event EnvOutHandler EnvOutput
- {
- add { currentFlowEnvironmentEvent.EnvOutput += value; }
- remove { currentFlowEnvironmentEvent.EnvOutput -= value; }
- }
-
-
-
///
public void ActivateFlipflopNode(string nodeGuid)
{
- currentFlowEnvironment.ActivateFlipflopNode(nodeGuid);
- }
-
- ///
- public void CreateCanvas(string canvasName, int width, int height)
- {
- currentFlowEnvironment.CreateCanvas(canvasName, width, height);
- }
-
- ///
- public void RemoveCanvas(string canvasGuid)
- {
- currentFlowEnvironment.RemoveCanvas(canvasGuid);
- }
-
- ///
- public void ConnectInvokeNode(string canvasGuid,
- string fromNodeGuid,
- string toNodeGuid,
- JunctionType fromNodeJunctionType,
- JunctionType toNodeJunctionType,
- ConnectionInvokeType invokeType)
- {
- currentFlowEnvironment.ConnectInvokeNode(canvasGuid, fromNodeGuid, toNodeGuid, fromNodeJunctionType, toNodeJunctionType, invokeType);
- }
-
- ///
- public void ConnectArgSourceNode(string canvasGuid,
- string fromNodeGuid,
- string toNodeGuid,
- JunctionType fromNodeJunctionType,
- JunctionType toNodeJunctionType,
- ConnectionArgSourceType argSourceType,
- int argIndex)
- {
- currentFlowEnvironment.ConnectArgSourceNode(canvasGuid, fromNodeGuid, toNodeGuid, fromNodeJunctionType, toNodeJunctionType, argSourceType, argIndex);
+ currentFlowEnvironment.FlowControl.ActivateFlipflopNode(nodeGuid);
}
///
@@ -320,42 +167,10 @@ namespace Serein.NodeFlow.Env
return (isConnect, remoteMsgUtil);
}
- ///
- public async Task LoadNodeInfosAsync(List nodeInfos)
- {
- SetProjectLoadingFlag(false);
- await currentFlowEnvironment.LoadNodeInfosAsync(nodeInfos); // 装饰器调用
- SetProjectLoadingFlag(true);
- }
-
- ///
- public void CreateNode(string canvasGuid, NodeControlType nodeBase, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null)
- {
- SetProjectLoadingFlag(false);
- currentFlowEnvironment.CreateNode(canvasGuid, nodeBase, position, methodDetailsInfo); // 装饰器调用
- SetProjectLoadingFlag(true);
- }
-
- ///
- public void PlaceNodeToContainer(string canvasGuid, string nodeGuid, string containerNodeGuid)
- {
- SetProjectLoadingFlag(false);
- currentFlowEnvironment.PlaceNodeToContainer(canvasGuid, nodeGuid, containerNodeGuid); // 装饰器调用
- SetProjectLoadingFlag(true);
- }
-
- ///
- public void TakeOutNodeToContainer(string canvasGuid, string nodeGuid)
- {
- SetProjectLoadingFlag(false);
- currentFlowEnvironment.TakeOutNodeToContainer(canvasGuid,nodeGuid); // 装饰器调用
- SetProjectLoadingFlag(true);
- }
-
///
public async Task ExitFlowAsync()
{
- return await currentFlowEnvironment.ExitFlowAsync();
+ return await currentFlowEnvironment.FlowControl.ExitFlowAsync();
}
///
@@ -401,19 +216,7 @@ namespace Serein.NodeFlow.Env
///
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
{
- currentFlowEnvironment.MonitorObjectNotification(nodeGuid, monitorData, sourceType);
- }
-
- /*///
- public void MoveNode(string canvasGuid, string nodeGuid, double x, double y)
- {
- currentFlowEnvironment.MoveNode(canvasGuid, nodeGuid, x, y);
- }
-*/
- ///
- public void NodeLocate(string nodeGuid)
- {
- currentFlowEnvironment.NodeLocate(nodeGuid);
+ currentFlowEnvironment.FlowControl.MonitorObjectNotification(nodeGuid, monitorData, sourceType);
}
///
@@ -422,31 +225,6 @@ namespace Serein.NodeFlow.Env
return currentFlowEnvironment.TryUnloadLibrary(assemblyName);
}
- ///
- public void SetConnectPriorityInvoke(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
- {
- currentFlowEnvironment.SetConnectPriorityInvoke(fromNodeGuid, toNodeGuid, connectionType);
- }
-
- ///
- public void RemoveInvokeConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
- {
- currentFlowEnvironment.RemoveInvokeConnect(canvasGuid, fromNodeGuid, toNodeGuid, connectionType);
- }
-
- ///
- public void RemoveArgSourceConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, int argIndex)
- {
- currentFlowEnvironment.RemoveArgSourceConnect(canvasGuid, fromNodeGuid, toNodeGuid, argIndex);
- }
-
- ///
- public void RemoveNode(string canvasGuid, string nodeGuid)
- {
- currentFlowEnvironment.RemoveNode(canvasGuid, nodeGuid);
- }
-
-
///
/// 输出信息
///
@@ -489,22 +267,17 @@ namespace Serein.NodeFlow.Env
#endregion
- ///
- public void SetStartNode(string canvasGuid, string nodeGuid)
- {
- currentFlowEnvironment.SetStartNode(canvasGuid, nodeGuid);
- }
///
public async Task StartFlowAsync(string[] canvasGuids)
{
- return await currentFlowEnvironment.StartFlowAsync(canvasGuids);
+ return await currentFlowEnvironment.FlowControl.StartFlowAsync(canvasGuids);
}
///
public async Task StartFlowFromSelectNodeAsync(string startNodeGuid)
{
- return await currentFlowEnvironment.StartFlowFromSelectNodeAsync(startNodeGuid);
+ return await currentFlowEnvironment.FlowControl.StartFlowFromSelectNodeAsync(startNodeGuid);
}
///
@@ -522,13 +295,13 @@ namespace Serein.NodeFlow.Env
///
public void TerminateFlipflopNode(string nodeGuid)
{
- currentFlowEnvironment.TerminateFlipflopNode(nodeGuid);
+ currentFlowEnvironment.FlowControl.TerminateFlipflopNode(nodeGuid);
}
///
public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type)
{
- currentFlowEnvironment.TriggerInterrupt(nodeGuid, expression, type);
+ currentFlowEnvironment.FlowControl.TriggerInterrupt(nodeGuid, expression, type);
}
///
@@ -545,7 +318,7 @@ namespace Serein.NodeFlow.Env
///
public void UseExternalIOC(ISereinIOC ioc)
{
- currentFlowEnvironment.UseExternalIOC(ioc);
+ currentFlowEnvironment.FlowControl.UseExternalIOC(ioc);
}
///
@@ -579,11 +352,6 @@ namespace Serein.NodeFlow.Env
}
}
- ///
- public void ChangeParameter(string nodeGuid, bool isAdd, int paramIndex)
- {
- currentFlowEnvironment.ChangeParameter(nodeGuid, isAdd, paramIndex);
- }
#region 流程依赖类库的接口
diff --git a/NodeFlow/Env/LocalFlowEnvironment.cs b/NodeFlow/Env/LocalFlowEnvironment.cs
index 51ddfcc..aaa3b2e 100644
--- a/NodeFlow/Env/LocalFlowEnvironment.cs
+++ b/NodeFlow/Env/LocalFlowEnvironment.cs
@@ -3,8 +3,6 @@ using Serein.Library.Api;
using Serein.Library.FlowNode;
using Serein.Library.Utils;
using Serein.Library.Utils.SereinExpression;
-using Serein.NodeFlow.Model;
-using Serein.NodeFlow.Model.Operation;
using Serein.NodeFlow.Services;
using Serein.NodeFlow.Tool;
using Serein.Script.Node;
@@ -17,6 +15,7 @@ using System.Reactive;
using System.Reflection;
using System.Security.AccessControl;
using System.Text;
+using static Serein.Library.Api.IFlowEnvironment;
namespace Serein.NodeFlow.Env
{
@@ -42,37 +41,23 @@ namespace Serein.NodeFlow.Env
FlowLibraryService flowLibraryManagement,
FlowOperationService flowOperationService,
FlowModelService flowModelService,
+ IFlowControl flowControl,
+ IFlowEdit flowEdit,
ISereinIOC sereinIOC,
NodeMVVMService nodeMVVMService)
{
- this.Event = flowEnvironmentEvent;
- this.NodeMVVMManagement = nodeMVVMService;
- this.flowOperationService = flowOperationService;
+ Event = flowEnvironmentEvent;
+ NodeMVVMManagement = nodeMVVMService;
+ FlowEdit = flowEdit;
+ FlowLibraryService = flowLibraryManagement;
+ IOC = sereinIOC;
this.flowModelService = flowModelService;
+ FlowControl = flowControl;
+ this.flowOperationService = flowOperationService;
this.IsGlobalInterrupt = false;
- this.FlowLibraryService = flowLibraryManagement;
this.flowEnvIOC = sereinIOC;
- this.IOC = sereinIOC;
- InitNodeMVVM();
}
- ///
- /// 注册基本节点类型
- ///
- private void InitNodeMVVM()
- {
- NodeMVVMManagement.RegisterModel(NodeControlType.UI, typeof(SingleUINode)); // 动作节点
- NodeMVVMManagement.RegisterModel(NodeControlType.Action, typeof(SingleActionNode)); // 动作节点
- NodeMVVMManagement.RegisterModel(NodeControlType.Flipflop, typeof(SingleFlipflopNode)); // 触发器节点
- NodeMVVMManagement.RegisterModel(NodeControlType.ExpOp, typeof(SingleExpOpNode)); // 表达式节点
- NodeMVVMManagement.RegisterModel(NodeControlType.ExpCondition, typeof(SingleConditionNode)); // 条件表达式节点
- NodeMVVMManagement.RegisterModel(NodeControlType.GlobalData, typeof(SingleGlobalDataNode)); // 全局数据节点
- NodeMVVMManagement.RegisterModel(NodeControlType.Script, typeof(SingleScriptNode)); // 脚本节点
- NodeMVVMManagement.RegisterModel(NodeControlType.NetScript, typeof(SingleNetScriptNode)); // 脚本节点
- NodeMVVMManagement.RegisterModel(NodeControlType.FlowCall, typeof(SingleFlowCallNode)); // 流程调用节点
- }
-
-
#region 远程管理
@@ -116,104 +101,6 @@ namespace Serein.NodeFlow.Env
#endregion
- #region 环境运行事件
- /*///
- /// 加载Dll
- ///
- public event LoadDllHandler? DllLoad;
-
- ///
- /// 移除DLL
- ///
- public event RemoteDllHandler? OnDllRemote;
-
- ///
- /// 项目加载完成
- ///
- public event ProjectLoadedHandler? ProjectLoaded;
-
- ///
- /// 项目准备保存
- ///
- public event ProjectSavingHandler? ProjectSaving;
-
- ///
- /// 节点连接属性改变事件
- ///
- public event NodeConnectChangeHandler? NodeConnectChanged;
-
- ///
- /// 节点创建事件
- ///
- public event NodeCreateHandler? NodeCreated;
-
- ///
- /// 移除节点事件
- ///
- public event NodeRemoveHandler? NodeRemoved;
-
- ///
- /// 节点放置事件
- ///
- public event NodePlaceHandler NodePlace;
-
- ///
- /// 节点取出事件
- ///
- public event NodeTakeOutHandler NodeTakeOut;
-
- ///
- /// 起始节点变化事件
- ///
- public event StartNodeChangeHandler? StartNodeChanged;
-
- ///
- /// 流程运行完成事件
- ///
- public event FlowRunCompleteHandler? FlowRunComplete;
-
- ///
- /// 被监视的对象改变事件
- ///
- public event MonitorObjectChangeHandler? MonitorObjectChanged;
-
- ///
- /// 节点中断状态改变事件
- ///
- public event NodeInterruptStateChangeHandler? NodeInterruptStateChanged;
-
- ///
- /// 节点触发了中断
- ///
- public event ExpInterruptTriggerHandler? InterruptTriggered;
-
- ///
- /// 容器改变
- ///
- public event IOCMembersChangedHandler? IOCMembersChanged;
-
- ///
- /// 节点需要定位
- ///
- public event NodeLocatedHandler? NodeLocated;
-
- ///
- /// 运行环境输出
- ///
- public event EnvOutHandler? EnvOutput;
-
- ///
- /// 本地环境添加了画布
- ///
- public event CanvasCreateHandler CanvasCreated;
-
- ///
- /// 本地环境移除了画布
- ///
- public event CanvasRemoveHandler CanvasRemoved;
-*/
- #endregion
-
#region 属性
///
@@ -226,6 +113,16 @@ namespace Serein.NodeFlow.Env
///
public IFlowEnvironmentEvent Event { get; set; }
+ ///
+ /// 流程编辑接口
+ ///
+ public IFlowEdit FlowEdit { get; set; }
+
+ ///
+ /// 流程控制接口
+ ///
+ public IFlowControl FlowControl { get; set; }
+
///
/// UI线程操作类
///
@@ -245,10 +142,6 @@ namespace Serein.NodeFlow.Env
/// 如果没有全局触发器,且没有循环分支,流程执行完成后自动为 Completion 。
///
public RunState FlowState { get; set; } = RunState.NoStart;
- ///
- /// 如果全局触发器还在运行,则为 Running 。
- ///
- public RunState FlipFlopState { get; set; } = RunState.NoStart;
///
/// 环境名称
@@ -364,205 +257,6 @@ namespace Serein.NodeFlow.Env
}
- ///
- /// 异步运行
- ///
- ///
- public async Task StartFlowAsync(string[] canvasGuids)
- {
- #region 校验参数
- HashSet guids = new HashSet();
- bool isBreak = false;
- foreach (var canvasGuid in canvasGuids)
- {
- if (guids.Contains(canvasGuid))
- {
- SereinEnv.WriteLine(InfoType.WARN, $"画布重复,停止运行。{canvasGuid}");
- isBreak = true;
- }
- else if (!flowModelService.ContainsCanvasModel(canvasGuid))
- {
- SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{canvasGuid}");
- isBreak = true;
- }
- else if(!flowModelService.IsExsitNodeOnCanvas(canvasGuid))
- {
- SereinEnv.WriteLine(InfoType.WARN, $"画布没有节点,停止运行。{canvasGuid}");
- isBreak = true;
- }
- else
- {
- guids.Add(canvasGuid);
- }
- }
- if (isBreak)
- {
- guids.Clear();
- return false;
- }
- #endregion
-
-
- #region 初始化每个画布的数据,转换为流程任务
- Dictionary flowTasks = [];
- foreach (var guid in guids)
- {
- if (!TryGetCanvasModel(guid, out var canvasModel))
- {
- SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{guid}");
- return false;
- }
- var ft = new FlowTask();
- ft.GetNodes = () => flowModelService.GetAllNodeModel(guid);
- if (canvasModel.StartNode?.Guid is null)
- {
- SereinEnv.WriteLine(InfoType.WARN, $"画布不存在起始节点,将停止运行。{guid}");
- return false;
- }
- ft.GetStartNode = () => canvasModel.StartNode;
- flowTasks.Add(guid, ft);
- }
- #endregion
-
- IOC.Reset();
- IOC.Register(()=> mainFlowEnvironment);
- IOC.Register(); // 注册脚本接口
-
- var flowTaskOptions = new FlowWorkOptions
- {
- Environment = this, // 流程
- Flows = flowTasks,
- FlowContextPool = new ObjectPool(() => new DynamicContext(this)), // 上下文对象池
- AutoRegisterTypes = this.FlowLibraryService.GetaAutoRegisterType(), // 需要自动实例化的类型
- InitMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Init),
- LoadMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Loading),
- ExitMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Exit),
- };
-
-
-
- flowTaskManagement = new FlowWorkManagement(flowTaskOptions);
- var cts = new CancellationTokenSource();
- try
- {
- var t = await flowTaskManagement.RunAsync(cts.Token);
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- }
- finally
- {
-
- SereinEnv.WriteLine(InfoType.INFO, $"流程运行完毕{Environment.NewLine}"); ;
- }
- flowTaskOptions = null;
- return true;
-
-
- }
-
-
- ///
- /// 从选定节点开始运行
- ///
- ///
- ///
- public async Task StartFlowFromSelectNodeAsync(string startNodeGuid)
- {
-
- var flowTaskOptions = new FlowWorkOptions
- {
- Environment = this, // 流程
- FlowContextPool = new ObjectPool(() => new DynamicContext(this)), // 上下文对象池
- };
- var flowTaskManagement = new FlowWorkManagement(flowTaskOptions);
-
- if (true || FlowState == RunState.Running || FlipFlopState == RunState.Running)
- {
-
- if (!TryGetNodeModel(startNodeGuid, out var nodeModel) || nodeModel is SingleFlipflopNode)
- {
- return false;
- }
- await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel);
- return true;
- }
- else
- {
- return false;
- }
- }
-
- /*///
- /// 单独运行一个节点
- ///
- ///
- ///
- public async Task InvokeNodeAsync(IDynamicContext context, string nodeGuid)
- {
- object result = Unit.Default;
- if (this.NodeModels.TryGetValue(nodeGuid, out var model))
- {
- CancellationTokenSource cts = new CancellationTokenSource();
- result = await model.ExecutingAsync(context, cts.Token);
- cts?.Cancel();
- }
- return result;
- }*/
-
- ///
- /// 结束流程
- ///
- public Task ExitFlowAsync()
- {
- flowTaskManagement?.Exit();
- UIContextOperation?.Invoke(() => Event.OnFlowRunComplete(new FlowEventArgs()));
- IOC.Reset();
- flowTaskManagement = null;
- GC.Collect();
- return Task.FromResult(true);
- }
-
- ///
- /// 激活全局触发器
- ///
- ///
- public void ActivateFlipflopNode(string nodeGuid)
- {
- /*if (!TryGetNodeModel(nodeGuid, out var nodeModel))
- {
- return;
- }
- if (nodeModel is null) return;
- if (flowTaskManagement is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
- {
- if (FlowState != RunState.Completion
- && flipflopNode.NotExitPreviousNode()) // 正在运行,且该触发器没有上游节点
- {
- _ = flowTaskManagement.RunGlobalFlipflopAsync(this, flipflopNode);// 被父节点移除连接关系的子节点若为触发器,且无上级节点,则当前流程正在运行,则加载到运行环境中
-
- }
- }*/
- }
-
- ///
- /// 关闭全局触发器
- ///
- ///
- public void TerminateFlipflopNode(string nodeGuid)
- {
- /* if (!TryGetNodeModel(nodeGuid, out var nodeModel))
- {
- return;
- }
- if (nodeModel is null) return;
- if (flowTaskManagement is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
- {
- flowTaskManagement.TerminateGlobalFlipflopRuning(flipflopNode);
- }*/
- }
-
///
/// 获取当前环境信息(远程连接)
///
@@ -622,12 +316,12 @@ namespace Serein.NodeFlow.Env
{
LoadCanvas(canvasInfo);
}
- await LoadNodeInfosAsync(projectData.Nodes.ToList()); // 加载节点信息
+ await FlowEdit.LoadNodeInfosAsync(projectData.Nodes.ToList()); // 加载节点信息
// 加载画布
foreach (var canvasInfo in projectData.Canvass)
{
- SetStartNode(canvasInfo.Guid, canvasInfo.StartNode); // 设置起始节点
+ FlowEdit.SetStartNode(canvasInfo.Guid, canvasInfo.StartNode); // 设置起始节点
}
//await SetStartNodeAsync("", projectData.StartNode); // 设置起始节点
});
@@ -900,35 +594,7 @@ namespace Serein.NodeFlow.Env
}
- ///
- public void UseExternalIOC(ISereinIOC ioc)
- {
- this.flowRunIOC = ioc; // 设置IOC容器
- }
-
- ///
- /// 启动器调用,运行到某个节点时触发了监视对象的更新(对象预览视图将会自动更新)
- ///
- ///
- ///
- ///
- public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
- {
- Event.OnMonitorObjectChanged(new MonitorObjectEventArgs(nodeGuid, monitorData, sourceType));
- }
-
- ///
- /// 启动器调用,节点触发了中断。
- ///
- /// 节点
- /// 表达式
- /// 类型,0用户主动的中断,1表达式中断
- public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type)
- {
- Event.OnInterruptTriggered(new InterruptTriggerEventArgs(nodeGuid, expression, type));
- }
-
-
+
/////
///// 环境执行中断
/////
@@ -1031,7 +697,6 @@ namespace Serein.NodeFlow.Env
#region 流程依赖类库的接口
-
///
/// 运行时加载
///
@@ -1055,725 +720,6 @@ namespace Serein.NodeFlow.Env
#endregion
- #region 私有方法
-
- #region 暂时注释
- /*
- ///
- /// 加载指定路径的DLL文件
- ///
- ///
- private void LoadDllNodeInfo(string dllPath)
- {
-
- var fileName = Path.GetFileName(dllPath);
- AssemblyLoadContext flowAlc = new AssemblyLoadContext(fileName, true);
- flowAlc.LoadFromAssemblyPath(dllPath); // 加载指定路径的程序集
-
- foreach(var assemblt in flowAlc.Assemblies)
- {
- (var registerTypes, var mdlist) = LoadAssembly(assemblt);
- if (mdlist.Count > 0)
- {
- var nodeLibraryInfo = new NodeLibraryInfo
- {
- //Assembly = assembly,
- AssemblyName = assemblt.FullName,
- FileName = Path.GetFileName(dllPath),
- FilePath = dllPath,
- };
-
- LibraryInfos.TryAdd(nodeLibraryInfo.AssemblyName, nodeLibraryInfo);
- MethodDetailsOfLibraryInfos.TryAdd(nodeLibraryInfo, mdlist);
-
- foreach (var md in mdlist)
- {
- MethodDetailss.TryAdd(md.MethodName, md);
- }
-
- foreach (var kv in registerTypes)
- {
- if (!AutoRegisterTypes.TryGetValue(kv.Key, out var types))
- {
- types = new List();
- AutoRegisterTypes.Add(kv.Key, types);
- }
- types.AddRange(kv.Value);
- }
- var mdInfos = mdlist.Select(md => md.ToInfo()).ToList(); // 转换成方法信息
-
- if (OperatingSystem.IsWindows())
- {
- UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibraryInfo, mdInfos))); // 通知UI创建dll面板显示
-
- }
- }
-
-
- }
-
-
-
-
- }*/
- #endregion
-
-
- ///
- /// 从节点信息创建节点,并返回状态指示是否创建成功
- ///
- ///
- ///
- private bool CreateNodeFromNodeInfo(NodeInfo nodeInfo)
- {
- if (!EnumHelper.TryConvertEnum(nodeInfo.Type, out var controlType))
- {
- return false;
- }
-
- #region 获取方法描述
- MethodDetails? methodDetails;
- if (controlType == NodeControlType.FlowCall)
- {
- if (string.IsNullOrEmpty(nodeInfo.MethodName))
- {
- methodDetails = new MethodDetails();
- methodDetails.ParamsArgIndex = 0;
- methodDetails.ParameterDetailss = new ParameterDetails[nodeInfo.ParameterData.Length];
- for (int i = 0; i < methodDetails.ParameterDetailss.Length; i++)
- {
- var pdInfo = nodeInfo.ParameterData[i];
- var t = new ParameterDetailsInfo();
- var pd = new ParameterDetails(pdInfo, i);
- methodDetails.ParameterDetailss[i] = pd;
- }
- }
- else
- {
- // 目标节点可能是方法节点
- FlowLibraryService.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName, out methodDetails); // 加载项目时尝试获取方法信息
- }
- }
- else if (controlType.IsBaseNode())
- {
- // 加载基础节点
- methodDetails = new MethodDetails();
-
- }
- else
- {
- if (string.IsNullOrEmpty(nodeInfo.MethodName)) return false;
- // 加载方法节点
- FlowLibraryService.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName, out methodDetails); // 加载项目时尝试获取方法信息
- }
- #endregion
-
- var nodeModel = FlowNodeExtension.CreateNode(this, controlType, methodDetails); // 加载项目时创建节点
- if (nodeModel is null)
- {
- nodeInfo.Guid = string.Empty;
- return false;
- }
- if (TryGetCanvasModel(nodeInfo.CanvasGuid, out var canvasModel))
- {
-
- // 节点与画布互相绑定
- // 需要在UI线程上进行添加,否则会报 “不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改”异常
- nodeModel.CanvasDetails = canvasModel;
- UIContextOperation?.Invoke(() => canvasModel.Nodes.Add(nodeModel));
-
- nodeModel.LoadInfo(nodeInfo); // 创建节点model
- TryAddNode(nodeModel); // 加载项目时将节点加载到环境中
- }
- else
- {
- SereinEnv.WriteLine(InfoType.ERROR, $"加载节点[{nodeInfo.Guid}]时发生异常,画布[{nodeInfo.CanvasGuid}]不存在");
- return false;
- }
-
- UIContextOperation?.Invoke(() =>
- Event.OnNodeCreated(new NodeCreateEventArgs(nodeInfo.CanvasGuid, nodeModel, nodeInfo.Position))); // 添加到UI上
- return true;
- }
-
-
-
- ///
- /// 创建节点
- ///
- ///
- private bool TryAddNode(IFlowNode nodeModel)
- {
- nodeModel.Guid ??= Guid.NewGuid().ToString();
- flowModelService.AddNodeModel(nodeModel);
-
-
- // 如果是触发器,则需要添加到专属集合中
- /*if (nodeModel is SingleFlipflopNode flipflopNode)
- {
- var guid = flipflopNode.Guid;
- if (!FlipflopNodes.Exists(it => it.Guid.Equals(guid)))
- {
- FlipflopNodes.Add(flipflopNode);
- }
- }*/
- return true;
- }
-
- ///
- /// 检查连接
- ///
- /// 发起连接的起始节点
- /// 要连接的目标节点
- /// 发起连接节点的控制点类型
- /// 被连接节点的控制点类型
- ///
- public static (JunctionOfConnectionType, bool) CheckConnect(IFlowNode fromNode,
- IFlowNode toNode,
- JunctionType fromNodeJunctionType,
- JunctionType toNodeJunctionType)
- {
- var type = JunctionOfConnectionType.None;
- var state = false;
- if (fromNodeJunctionType == JunctionType.Execute)
- {
- if (toNodeJunctionType == JunctionType.NextStep && !fromNode.Guid.Equals(toNode.Guid))
- {
- // “方法执行”控制点拖拽到“下一节点”控制点,且不是同一个节点, 添加方法执行关系
- type = JunctionOfConnectionType.Invoke;
- state = true;
- }
- //else if (toNodeJunctionType == JunctionType.ArgData && fromNode.Guid.Equals(toNode.Guid))
- //{
- // // “方法执行”控制点拖拽到“方法入参”控制点,且是同一个节点,则添加获取参数关系,表示生成入参参数时自动从该节点的上一节点获取flowdata
- // type = JunctionOfConnectionType.Arg;
- // state = true;
- //}
- }
- else if (fromNodeJunctionType == JunctionType.NextStep && !fromNode.Guid.Equals(toNode.Guid))
- {
- // “下一节点”控制点只能拖拽到“方法执行”控制点,且不能是同一个节点
- if (toNodeJunctionType == JunctionType.Execute && !fromNode.Guid.Equals(toNode.Guid))
- {
- type = JunctionOfConnectionType.Invoke;
- state = true;
- }
- }
- else if (fromNodeJunctionType == JunctionType.ArgData)
- {
- //if (toNodeJunctionType == JunctionType.Execute && fromNode.Guid.Equals(toNode.Guid)) // 添加获取参数关系
- //{
- // // “方法入参”控制点拖拽到“方法执行”控制点,且是同一个节点,则添加获取参数关系,生成入参参数时自动从该节点的上一节点获取flowdata
- // type = JunctionOfConnectionType.Arg;
- // state = true;
- //}
- if (toNodeJunctionType == JunctionType.ReturnData && !fromNode.Guid.Equals(toNode.Guid))
- {
- // “”控制点拖拽到“方法返回值”控制点,且不是同一个节点,添加获取参数关系,生成参数时从目标节点获取flowdata
- type = JunctionOfConnectionType.Arg;
- state = true;
- }
- }
- else if (fromNodeJunctionType == JunctionType.ReturnData)
- {
- if (toNodeJunctionType == JunctionType.ArgData && !fromNode.Guid.Equals(toNode.Guid))
- {
- // “方法返回值”控制点拖拽到“方法入参”控制点,且不是同一个节点,添加获取参数关系,生成参数时从目标节点获取flowdata
- type = JunctionOfConnectionType.Arg;
- state = true;
- }
- }
- // 剩下的情况都是不符预期的连接行为,忽略。
- return (type, state);
- }
- /*
- ///
- /// 连接节点
- ///
- /// 起始节点
- /// 目标节点
- /// 连接关系
- private bool ConnectInvokeOfNode(string canvasGuid, IFlowNode fromNode, IFlowNode toNode, ConnectionInvokeType invokeType)
- {
- if (fromNode.ControlType == NodeControlType.FlowCall)
- {
- SereinEnv.WriteLine(InfoType.ERROR, $"流程接口节点不可调用下一个节点。" +
- $"{Environment.NewLine}流程节点:{fromNode.Guid}");
- return false;
- }
- if (!FlowCanvass.ContainsKey(canvasGuid))
- {
- return false;
- }
- if (fromNode is null || toNode is null || fromNode == toNode)
- {
- return false;
- }
-
- var ToExistOnFrom = true;
- var FromExistInTo = true;
- ConnectionInvokeType[] ct = [ConnectionInvokeType.IsSucceed,
- ConnectionInvokeType.IsFail,
- ConnectionInvokeType.IsError,
- ConnectionInvokeType.Upstream];
-
- //if (toNode is SingleFlipflopNode flipflopNode)
- //{
- // flowTaskManagement?.TerminateGlobalFlipflopRuning(flipflopNode); // 假设被连接的是全局触发器,尝试移除
- //}
- var isOverwriting = false;
- ConnectionInvokeType overwritingCt = ConnectionInvokeType.None;
- var isPass = false;
- foreach (ConnectionInvokeType ctType in ct)
- {
- var FToTo = fromNode.SuccessorNodes[ctType].Where(it => it.Guid.Equals(toNode.Guid)).ToArray();
- var ToOnF = toNode.PreviousNodes[ctType].Where(it => it.Guid.Equals(fromNode.Guid)).ToArray();
- ToExistOnFrom = FToTo.Length > 0;
- FromExistInTo = ToOnF.Length > 0;
- if (ToExistOnFrom && FromExistInTo)
- {
- if (ctType == invokeType)
- {
- SereinEnv.WriteLine(InfoType.WARN, $"起始节点已与目标节点存在连接。" +
- $"{Environment.NewLine}起始节点:{fromNode.Guid}" +
- $"{Environment.NewLine}目标节点:{toNode.Guid}");
- return false;
- }
- isOverwriting = true;
- overwritingCt = ctType;
- }
- else
- {
- // 检查是否可能存在异常
- if (!ToExistOnFrom && FromExistInTo)
- {
- SereinEnv.WriteLine(InfoType.ERROR, $"起始节点不是目标节点的父节点,目标节点却是起始节点的子节点。" +
- $"{Environment.NewLine}起始节点:{fromNode.Guid}" +
- $"{Environment.NewLine}目标节点:{toNode.Guid}");
- isPass = false;
- }
- else if (ToExistOnFrom && !FromExistInTo)
- {
- //
- SereinEnv.WriteLine(InfoType.ERROR, $"起始节点不是目标节点的父节点,目标节点却是起始节点的子节点。" +
- $"{Environment.NewLine}起始节点:{fromNode.Guid}" +
- $"{Environment.NewLine}目标节点:{toNode.Guid}" +
- $"");
- isPass = false;
- }
- else
- {
- isPass = true;
- }
- }
- }
- if (isPass)
- {
- if (isOverwriting) // 需要替换
- {
- fromNode.SuccessorNodes[overwritingCt].Remove(toNode); // 从起始节点子分支中移除
- toNode.PreviousNodes[overwritingCt].Remove(fromNode); // 从目标节点父分支中移除
- }
- fromNode.SuccessorNodes[invokeType].Add(toNode); // 添加到起始节点的子分支
- toNode.PreviousNodes[invokeType].Add(fromNode); // 添加到目标节点的父分支
- if (OperatingSystem.IsWindows())
- {
-
- UIContextOperation?.Invoke(() =>
- Event.OnNodeConnectChanged(
- new NodeConnectChangeEventArgs(
- canvasGuid,
- fromNode.Guid, // 从哪个节点开始
- toNode.Guid, // 连接到那个节点
- JunctionOfConnectionType.Invoke,
- invokeType, // 连接线的样式类型
- NodeConnectChangeEventArgs.ConnectChangeType.Create // 是创建连接还是删除连接
- ))); // 通知UI
- }
- // Invoke
- // GetResult
- return true;
- }
- else
- {
- return false;
- }
-
-
- }*/
-
-
-
- ///
- /// 更改起点节点
- ///
- /// 节点所在的画布
- /// 起始节点
- private void SetStartNode(FlowCanvasDetails cavnasModel, IFlowNode newStartNode)
- {
- var oldNodeGuid = cavnasModel.StartNode?.Guid;
- /*if(TryGetNodeModel(oldNodeGuid, out var newStartNodeModel))
- {
- newStartNode.IsStart = false;
- }*/
- cavnasModel.StartNode = newStartNode;
- //newStartNode.IsStart = true;
- UIContextOperation?.Invoke(() => Event.OnStartNodeChanged(new StartNodeChangeEventArgs(cavnasModel.Guid, oldNodeGuid, cavnasModel.StartNode.Guid)));
-
- }
-
-
-
- #endregion
-
- #region 视觉效果
-
- ///
- /// 定位节点
- ///
- ///
- public void NodeLocate(string nodeGuid)
- {
- if (OperatingSystem.IsWindows())
- {
- UIContextOperation?.Invoke(() => Event.OnNodeLocated(new NodeLocatedEventArgs(nodeGuid)));
- }
-
- }
-
-
- #endregion
-
-
-
- #region 流程接口
-
- private int _add_canvas_count = 1;
- public void CreateCanvas(string canvasName, int width, int height)
- {
- IOperation operation = new CreateCanvasOperation
- {
- CanvasInfo = new FlowCanvasDetailsInfo
- {
- Name = $"Canvas {_add_canvas_count++}",
- Width = width,
- Height = height,
- Guid = Guid.NewGuid().ToString(),
- ScaleX = 1.0f,
- ScaleY = 1.0f,
- }
- };
-
- flowOperationService.Execute(operation);
- }
-
- public void RemoveCanvas(string canvasGuid)
- {
- IOperation operation = new RemoveCanvasOperation
- {
- CanvasGuid = canvasGuid
- };
- flowOperationService.Execute(operation);
- }
-
- public void ConnectInvokeNode(string canvasGuid, string fromNodeGuid, string toNodeGuid, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType, ConnectionInvokeType invokeType)
- {
- IOperation operation = new ChangeNodeConnectionOperation
- {
- CanvasGuid = canvasGuid,
- FromNodeGuid = fromNodeGuid,
- ToNodeGuid = toNodeGuid,
- FromNodeJunctionType = fromNodeJunctionType,
- ToNodeJunctionType = toNodeJunctionType,
- ConnectionInvokeType = invokeType,
- ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Create,
- JunctionOfConnectionType = JunctionOfConnectionType.Invoke,
- };
-
- flowOperationService.Execute(operation);
- }
-
- public void ConnectArgSourceNode(string canvasGuid, string fromNodeGuid, string toNodeGuid, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType, ConnectionArgSourceType argSourceType, int argIndex)
- {
- IOperation operation = new ChangeNodeConnectionOperation
- {
- CanvasGuid = canvasGuid,
- FromNodeGuid = fromNodeGuid,
- ToNodeGuid = toNodeGuid,
- FromNodeJunctionType = fromNodeJunctionType,
- ToNodeJunctionType = toNodeJunctionType,
- ConnectionArgSourceType = argSourceType,
- ArgIndex = argIndex,
- ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Create,
- JunctionOfConnectionType = JunctionOfConnectionType.Arg,
- };
- flowOperationService.Execute(operation);
- }
-
- public void RemoveInvokeConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
- {
- IOperation operation = new ChangeNodeConnectionOperation
- {
- CanvasGuid = canvasGuid,
- FromNodeGuid = fromNodeGuid,
- ToNodeGuid = toNodeGuid,
- ConnectionInvokeType = connectionType,
- ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Remove,
- };
- flowOperationService.Execute(operation);
- }
-
- public void RemoveArgSourceConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, int argIndex)
- {
- IOperation operation = new ChangeNodeConnectionOperation
- {
- CanvasGuid = canvasGuid,
- FromNodeGuid = fromNodeGuid,
- ToNodeGuid = toNodeGuid,
- ArgIndex = argIndex,
- ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Remove
- };
- flowOperationService.Execute(operation);
- }
-
- public void CreateNode(string canvasGuid, NodeControlType nodeType, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null)
- {
- IOperation operation = new CreateNodeOperation
- {
- CanvasGuid = canvasGuid,
- NodeControlType = nodeType,
- Position = position,
- MethodDetailsInfo = methodDetailsInfo
- };
- flowOperationService.Execute(operation);
- }
-
- public void RemoveNode(string canvasGuid, string nodeGuid)
- {
- IOperation operation = new RemoveNodeOperation
- {
- CanvasGuid = canvasGuid,
- NodeGuid = nodeGuid
- };
- flowOperationService.Execute(operation);
- }
-
- public void PlaceNodeToContainer(string canvasGuid, string nodeGuid, string containerNodeGuid)
- {
- IOperation operation = new ContainerPlaceNodeOperation
- {
- CanvasGuid = canvasGuid,
- NodeGuid = nodeGuid,
- ContainerNodeGuid = containerNodeGuid
- };
- flowOperationService.Execute(operation);
- }
-
- public void TakeOutNodeToContainer(string canvasGuid, string nodeGuid)
- {
- IOperation operation = new ContainerTakeOutNodeOperation
- {
- CanvasGuid = canvasGuid,
- NodeGuid = nodeGuid,
- };
- flowOperationService.Execute(operation);
- }
-
- public void SetStartNode(string canvasGuid, string nodeGuid)
- {
- if (!TryGetCanvasModel(canvasGuid, out var canvasModel) || !TryGetNodeModel(nodeGuid, out var newStartNodeModel))
- {
- return;
- }
- SetStartNode(canvasModel, newStartNodeModel);
- return;
- }
-
- void IFlowEnvironment.SetConnectPriorityInvoke(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
- {
-
- IOperation operation = new ChangeNodeConnectionOperation
- {
- CanvasGuid = string.Empty, // 连接优先级不需要画布
- FromNodeGuid = fromNodeGuid,
- ToNodeGuid = toNodeGuid,
- ConnectionInvokeType = connectionType,
- ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Create
- };
- flowOperationService.Execute(operation);
- }
-
- public void ChangeParameter(string nodeGuid, bool isAdd, int paramIndex)
- {
- IOperation operation = new ChangeParameterOperation
- {
- NodeGuid = nodeGuid,
- IsAdd = isAdd,
- ParamIndex = paramIndex
- };
- flowOperationService.Execute(operation);
- }
-
-
-
- ///
- /// 从节点信息集合批量加载节点控件
- ///
- /// 节点信息
- ///
- ///
- public async Task LoadNodeInfosAsync(List nodeInfos)
- {
- #region 从NodeInfo创建NodeModel
- // 流程接口节点最后才创建
-
- List flowCallNodeInfos = [];
- foreach (NodeInfo? nodeInfo in nodeInfos)
- {
- if (nodeInfo.Type == nameof(NodeControlType.FlowCall))
- {
- flowCallNodeInfos.Add(nodeInfo);
- }
- else
- {
- if (!CreateNodeFromNodeInfo(nodeInfo))
- {
- SereinEnv.WriteLine(InfoType.WARN, $"节点创建失败。{Environment.NewLine}{nodeInfo}");
- continue;
- }
- }
- }
-
- // 创建流程接口节点
- foreach (NodeInfo? nodeInfo in flowCallNodeInfos)
- {
- if (!CreateNodeFromNodeInfo(nodeInfo))
- {
- SereinEnv.WriteLine(InfoType.WARN, $"节点创建失败。{Environment.NewLine}{nodeInfo}");
- continue;
- }
- }
- #endregion
-
- #region 重新放置节点
-
- List needPlaceNodeInfos = [];
- foreach (NodeInfo? nodeInfo in nodeInfos)
- {
- if (!string.IsNullOrEmpty(nodeInfo.ParentNodeGuid) &&
- TryGetNodeModel(nodeInfo.ParentNodeGuid, out var parentNode))
- {
- needPlaceNodeInfos.Add(nodeInfo); // 需要重新放置的节点
- }
- }
-
- foreach (NodeInfo nodeInfo in needPlaceNodeInfos)
- {
- if (TryGetNodeModel(nodeInfo.Guid, out var nodeModel) &&
- TryGetNodeModel(nodeInfo.ParentNodeGuid, out var containerNode)
- && containerNode is INodeContainer nodeContainer)
- {
- var result = nodeContainer.PlaceNode(nodeModel);
- if (result)
- {
- UIContextOperation?.Invoke(() => Event.OnNodePlace(
- new NodePlaceEventArgs(nodeInfo.CanvasGuid, nodeModel.Guid, containerNode.Guid)));
- }
-
-
- }
- }
- #endregion
-
- await Task.Delay(100);
- #region 确定节点之间的方法调用关系
- foreach (var nodeInfo in nodeInfos)
- {
- var canvasGuid = nodeInfo.CanvasGuid;
- 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),
- (ConnectionInvokeType.IsError, nodeInfo.ErrorNodes),
- (ConnectionInvokeType.Upstream, nodeInfo.UpstreamNodes)];
- foreach ((ConnectionInvokeType connectionType, string[] toNodeGuids) item in allToNodes)
- {
- // 遍历当前类型分支的节点(确认连接关系)
- foreach (var toNodeGuid in item.toNodeGuids)
- {
- if (!TryGetNodeModel(toNodeGuid, out var toNodeModel))
- {
- return;
- }
- if (toNodeModel is null)
- {
- // 防御性代码,加载正常保存的项目文件不会进入这里
- continue;
- }
-
- ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.NextStep, JunctionType.Execute, item.connectionType);
-
- //var isSuccessful = ConnectInvokeOfNode(canvasGuid, fromNodeModel, toNodeModel, item.connectionType); // 加载时确定节点间的连接关系
- }
- }
-
-
- //List<(ConnectionInvokeType connectionType, string[] guids)> allToNodes = [(ConnectionInvokeType.IsSucceed,nodeInfo.TrueNodes),
- // (ConnectionInvokeType.IsFail, nodeInfo.FalseNodes),
- // (ConnectionInvokeType.IsError, nodeInfo.ErrorNodes),
- // (ConnectionInvokeType.Upstream, nodeInfo.UpstreamNodes)];
-
- //List<(ConnectionInvokeType, NodeModelBase[])> fromNodes = allToNodes.Where(info => info.guids.Length > 0)
- // .Select(info => (info.connectionType,
- // info.guids.Where(guid => NodeModels.ContainsKey(guid)).Select(guid => NodeModels[guid])
- // .ToArray()))
- // .ToList();
- // 遍历每种类型的节点分支(四种)
- //foreach ((ConnectionInvokeType connectionType, NodeModelBase[] toNodes) item in nodeInfo)
- //{
- // // 遍历当前类型分支的节点(确认连接关系)
- // foreach (var toNode in item.toNodes)
- // {
- // _ = ConnectInvokeOfNode(fromNode, toNode, item.connectionType); // 加载时确定节点间的连接关系
- // }
- //}
- }
- #endregion
-
- #region 确定节点之间的参数调用关系
- var nodeModels = flowModelService.GetAllNodeModel();
- foreach (var toNode in nodeModels)
- {
- var canvasGuid = toNode.CanvasDetails.Guid;
- if (toNode.MethodDetails.ParameterDetailss == null)
- {
- continue;
- }
- for (var i = 0; i < toNode.MethodDetails.ParameterDetailss.Length; i++)
- {
- var pd = toNode.MethodDetails.ParameterDetailss[i];
- if (!string.IsNullOrEmpty(pd.ArgDataSourceNodeGuid)
- && TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var fromNode))
- {
-
- ConnectArgSourceNode(canvasGuid, fromNode.Guid, toNode.Guid, JunctionType.ReturnData, JunctionType.ArgData , pd.ArgDataSourceType, pd.Index);
- }
- }
- }
- #endregion
-
-
- UIContextOperation?.Invoke(() =>
- {
- Event.OnProjectLoaded(new ProjectLoadedEventArgs());
- });
-
- return;
- }
- #endregion
}
diff --git a/NodeFlow/FlowNodeExtension.cs b/NodeFlow/FlowNodeExtension.cs
index 67f5d1d..f2c12a4 100644
--- a/NodeFlow/FlowNodeExtension.cs
+++ b/NodeFlow/FlowNodeExtension.cs
@@ -43,7 +43,7 @@ namespace Serein.NodeFlow
// 尝试获取需要创建的节点类型
- if (!env.NodeMVVMManagement.TryGetType(nodeControlType, out var nodeMVVM) || nodeMVVM.ModelType == null)
+ if (!env.FlowEdit.NodeMVVMManagement.TryGetType(nodeControlType, out var nodeMVVM) || nodeMVVM.ModelType == null)
{
throw new Exception($"无法创建{nodeControlType}节点,节点类型尚未注册。");
}
diff --git a/NodeFlow/Model/Node/NodeModelBaseFunc.cs b/NodeFlow/Model/Node/NodeModelBaseFunc.cs
index d1ce2d8..9a49e37 100644
--- a/NodeFlow/Model/Node/NodeModelBaseFunc.cs
+++ b/NodeFlow/Model/Node/NodeModelBaseFunc.cs
@@ -115,7 +115,7 @@ namespace Serein.NodeFlow.Model
// 执行触发检查是否需要中断
if (DebugSetting.IsInterrupt)
{
- context.Env.TriggerInterrupt(Guid, "", InterruptTriggerEventArgs.InterruptTriggerType.Monitor); // 通知运行环境该节点中断了
+ context.Env.FlowControl.TriggerInterrupt(Guid, "", InterruptTriggerEventArgs.InterruptTriggerType.Monitor); // 通知运行环境该节点中断了
await DebugSetting.GetInterruptTask.Invoke();
SereinEnv.WriteLine(InfoType.INFO, $"[{this.MethodDetails?.MethodName}]中断已取消,开始执行后继分支");
if (token.IsCancellationRequested) { return null; }
diff --git a/NodeFlow/Model/Node/SingleFlowCallNode.cs b/NodeFlow/Model/Node/SingleFlowCallNode.cs
index 7987162..eddc5eb 100644
--- a/NodeFlow/Model/Node/SingleFlowCallNode.cs
+++ b/NodeFlow/Model/Node/SingleFlowCallNode.cs
@@ -38,17 +38,15 @@ namespace Serein.NodeFlow.Model
public partial class SingleFlowCallNode : NodeModelBase
{
///
- /// 接口节点
+ /// 被调用的节点
///
private IFlowNode targetNode;
///
/// 缓存的方法信息
///
public MethodDetails CacheMethodDetails { get; private set; }
- ///
- /// 接口节点Guid
- ///
- //public string? TargetNodeGuid => targetNode?.Guid;
+
+
public SingleFlowCallNode(IFlowEnvironment environment) : base(environment)
diff --git a/NodeFlow/Model/Node/SingleGlobalDataNode.cs b/NodeFlow/Model/Node/SingleGlobalDataNode.cs
index 6bda89a..27f1064 100644
--- a/NodeFlow/Model/Node/SingleGlobalDataNode.cs
+++ b/NodeFlow/Model/Node/SingleGlobalDataNode.cs
@@ -96,7 +96,7 @@ namespace Serein.NodeFlow.Model
{
foreach (var nodeModel in ChildrenNode)
{
- nodeModel.Env.TakeOutNodeToContainer(nodeModel.CanvasDetails.Guid, nodeModel.Guid);
+ nodeModel.Env.FlowEdit.TakeOutNodeToContainer(nodeModel.CanvasDetails.Guid, nodeModel.Guid);
}
DataNode = null;
}
diff --git a/NodeFlow/Model/Operation/CreateNodeOperation.cs b/NodeFlow/Model/Operation/CreateNodeOperation.cs
index aaf3250..e688504 100644
--- a/NodeFlow/Model/Operation/CreateNodeOperation.cs
+++ b/NodeFlow/Model/Operation/CreateNodeOperation.cs
@@ -112,7 +112,7 @@ namespace Serein.NodeFlow.Model.Operation
if(flowNode is null) return false; // 没有创建过节点
var canvasGuid = flowCanvasDetails.Guid;
var nodeGuid = flowNode.Guid;
- flowEnvironment.RemoveNode(canvasGuid, nodeGuid);
+ flowEnvironment.FlowEdit.RemoveNode(canvasGuid, nodeGuid);
return true;
}
diff --git a/NodeFlow/Services/FlowApiService.cs b/NodeFlow/Services/FlowApiService.cs
index 4c8fd53..cee0599 100644
--- a/NodeFlow/Services/FlowApiService.cs
+++ b/NodeFlow/Services/FlowApiService.cs
@@ -5,7 +5,6 @@ using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxTokenParser;
namespace Serein.NodeFlow.Services
{
@@ -31,32 +30,6 @@ namespace Serein.NodeFlow.Services
- /* object result = flowApiService.Invoke("", params);
- TResult result = flowApiService.Invoke("", params);
- object result = await flowApiService.InvokeAsync("", params);
- TResult result = await flowApiService.InvokeAsync("", params);*/
-
-
- public object Invoke(string apiName, object[] param)
- {
- return null;
- }
-
- public TResult Invoke(string apiName, object[] param)
- {
- return default(TResult);
- }
-
- public async Task InvokeAsync(string apiName, object[] param)
- {
- return null;
- }
-
- public async Task InvokeAsync(string apiName, object[] param)
- {
- return default(TResult);
-
- }
}
diff --git a/Workbench/Node/Junction/JunctionControlBase.cs b/Workbench/Node/Junction/JunctionControlBase.cs
index eb1fe6e..2fbdaf8 100644
--- a/Workbench/Node/Junction/JunctionControlBase.cs
+++ b/Workbench/Node/Junction/JunctionControlBase.cs
@@ -159,11 +159,11 @@ namespace Serein.Workbench.Node.View
private void AddParamAsync()
{
- this.MyNode.Env.ChangeParameter(MyNode.Guid, true, ArgIndex);
+ this.MyNode.Env.FlowEdit.ChangeParameter(MyNode.Guid, true, ArgIndex);
}
private void RemoveParamAsync()
{
- this.MyNode.Env.ChangeParameter(MyNode.Guid, false, ArgIndex);
+ this.MyNode.Env.FlowEdit.ChangeParameter(MyNode.Guid, false, ArgIndex);
}
}
diff --git a/Workbench/Node/View/ConnectionControl.cs b/Workbench/Node/View/ConnectionControl.cs
index 0cbbb30..b94272a 100644
--- a/Workbench/Node/View/ConnectionControl.cs
+++ b/Workbench/Node/View/ConnectionControl.cs
@@ -243,11 +243,11 @@ namespace Serein.Workbench.Node.View
var jctEnd = End.JunctionType.ToConnectyionType();
if (jct == JunctionOfConnectionType.Invoke)
{
- env.RemoveInvokeConnect(canvasGuid, Start.MyNode.Guid, End.MyNode.Guid, InvokeType);
+ env.FlowEdit.RemoveInvokeConnect(canvasGuid, Start.MyNode.Guid, End.MyNode.Guid, InvokeType);
}
else if (jct == JunctionOfConnectionType.Arg)
{
- env.RemoveArgSourceConnect(canvasGuid,Start.MyNode.Guid, End.MyNode.Guid, ArgIndex) ;
+ env.FlowEdit.RemoveArgSourceConnect(canvasGuid,Start.MyNode.Guid, End.MyNode.Guid, ArgIndex) ;
}
}
@@ -259,7 +259,7 @@ namespace Serein.Workbench.Node.View
var env = Start.MyNode.Env;
if (Start.JunctionType.ToConnectyionType() == JunctionOfConnectionType.Invoke)
{
- env.SetConnectPriorityInvoke(Start.MyNode.Guid, End.MyNode.Guid, InvokeType);
+ env.FlowEdit.SetConnectPriorityInvoke(Start.MyNode.Guid, End.MyNode.Guid, InvokeType);
}
}
diff --git a/Workbench/Services/FlowNodeService.cs b/Workbench/Services/FlowNodeService.cs
index 509794f..41b6562 100644
--- a/Workbench/Services/FlowNodeService.cs
+++ b/Workbench/Services/FlowNodeService.cs
@@ -174,15 +174,15 @@ namespace Serein.Workbench.Services
///
private void InitNodeType()
{
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.UI, typeof(UINodeControl), typeof(UINodeControlViewModel));
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.Action, typeof(ActionNodeControl), typeof(ActionNodeControlViewModel));
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.Flipflop, typeof(FlipflopNodeControl), typeof(FlipflopNodeControlViewModel));
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.ExpOp, typeof(ExpOpNodeControl), typeof(ExpOpNodeControlViewModel));
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.ExpCondition, typeof(ConditionNodeControl), typeof(ConditionNodeControlViewModel));
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.GlobalData, typeof(GlobalDataControl), typeof(GlobalDataNodeControlViewModel));
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.Script, typeof(ScriptNodeControl), typeof(ScriptNodeControlViewModel));
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.NetScript, typeof(NetScriptNodeControl), typeof(NetScriptNodeControlViewModel));
- flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.FlowCall, typeof(FlowCallNodeControl), typeof(FlowCallNodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.UI, typeof(UINodeControl), typeof(UINodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.Action, typeof(ActionNodeControl), typeof(ActionNodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.Flipflop, typeof(FlipflopNodeControl), typeof(FlipflopNodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.ExpOp, typeof(ExpOpNodeControl), typeof(ExpOpNodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.ExpCondition, typeof(ConditionNodeControl), typeof(ConditionNodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.GlobalData, typeof(GlobalDataControl), typeof(GlobalDataNodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.Script, typeof(ScriptNodeControl), typeof(ScriptNodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.NetScript, typeof(NetScriptNodeControl), typeof(NetScriptNodeControlViewModel));
+ flowEnvironment.FlowEdit.NodeMVVMManagement.RegisterUI(NodeControlType.FlowCall, typeof(FlowCallNodeControl), typeof(FlowCallNodeControlViewModel));
}
///
@@ -319,7 +319,7 @@ namespace Serein.Workbench.Services
return;
}
- if (!flowEnvironment.NodeMVVMManagement.TryGetType(nodeModel.ControlType, out var nodeMVVM))
+ if (!flowEnvironment.FlowEdit.NodeMVVMManagement.TryGetType(nodeModel.ControlType, out var nodeMVVM))
{
SereinEnv.WriteLine(InfoType.INFO, $"无法创建{nodeModel.ControlType}节点,节点类型尚未注册。");
return;
@@ -635,7 +635,7 @@ namespace Serein.Workbench.Services
node.Position = new PositionOfUI(positionOfUI.X + offsetX, positionOfUI.Y + offsetY);
}
- _ = flowEnvironment.LoadNodeInfosAsync(nodes);
+ _ = flowEnvironment.FlowEdit.LoadNodeInfosAsync(nodes);
}
catch (Exception ex)
{
@@ -656,7 +656,7 @@ namespace Serein.Workbench.Services
{
int width = 1200;
int height = 780;
- flowEnvironment.CreateCanvas("", width, height);
+ flowEnvironment.FlowEdit.CreateCanvas("", width, height);
}
///
@@ -669,7 +669,7 @@ namespace Serein.Workbench.Services
return;
}
var model = ((FlowCanvasViewModel)CurrentSelectCanvas.DataContext).Model;
- flowEnvironment.RemoveCanvas(model.Guid);
+ flowEnvironment.FlowEdit.RemoveCanvas(model.Guid);
}
///
@@ -688,7 +688,7 @@ namespace Serein.Workbench.Services
{
return;
}
- flowEnvironment.CreateNode(canvasGuid, nodeType, position, methodDetailsInfo);
+ flowEnvironment.FlowEdit.CreateNode(canvasGuid, nodeType, position, methodDetailsInfo);
}
///
@@ -707,7 +707,7 @@ namespace Serein.Workbench.Services
return;
}
- flowEnvironment.RemoveNode(model.CanvasDetails.Guid, model.Guid);
+ flowEnvironment.FlowEdit.RemoveNode(model.CanvasDetails.Guid, model.Guid);
}
#endregion
diff --git a/Workbench/Themes/NodeTreeItemViewControl.xaml.cs b/Workbench/Themes/NodeTreeItemViewControl.xaml.cs
index b348f88..be6f0f1 100644
--- a/Workbench/Themes/NodeTreeItemViewControl.xaml.cs
+++ b/Workbench/Themes/NodeTreeItemViewControl.xaml.cs
@@ -142,7 +142,7 @@ namespace Serein.Workbench.Themes
{
try
{
- await flowEnvironment.StartFlowFromSelectNodeAsync(tmpNodeTreeModel.RootNode.Guid);
+ await flowEnvironment.FlowControl.StartFlowFromSelectNodeAsync(tmpNodeTreeModel.RootNode.Guid);
}
catch (Exception ex)
{
@@ -150,7 +150,7 @@ namespace Serein.Workbench.Themes
return;
}
}));
- contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("定位", (s, e) => flowEnvironment.NodeLocate(tmpNodeTreeModel.RootNode.Guid)));
+ contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("定位", (s, e) => flowEnvironment.FlowEdit.NodeLocate(tmpNodeTreeModel.RootNode.Guid)));
treeViewItem.ContextMenu = contextMenu;
treeViewItem.Margin = new Thickness(-20, 0, 0, 0);
diff --git a/Workbench/ViewModels/MainMenuBarViewModel.cs b/Workbench/ViewModels/MainMenuBarViewModel.cs
index c8f5e8e..2f25672 100644
--- a/Workbench/ViewModels/MainMenuBarViewModel.cs
+++ b/Workbench/ViewModels/MainMenuBarViewModel.cs
@@ -114,7 +114,7 @@ namespace Serein.Workbench.ViewModels
if(canvass.Length > 0)
{
string[] guids = [..canvass.Select(c => c.Guid)];
- flowEnvironment.StartFlowAsync(guids);
+ flowEnvironment.FlowControl.StartFlowAsync(guids);
}
}
@@ -122,7 +122,7 @@ namespace Serein.Workbench.ViewModels
{
var canvas = flowNodeService.CurrentSelectCanvas;
if (canvas is null) return;
- flowEnvironment.StartFlowAsync([canvas.Guid]);
+ flowEnvironment.FlowControl.StartFlowAsync([canvas.Guid]);
}
private void StopCurrentCanvasFlow() { }
private void OpenDynamicCompiler() { }
diff --git a/Workbench/Views/FlowCanvasView.xaml.cs b/Workbench/Views/FlowCanvasView.xaml.cs
index de827c4..6e33c43 100644
--- a/Workbench/Views/FlowCanvasView.xaml.cs
+++ b/Workbench/Views/FlowCanvasView.xaml.cs
@@ -370,7 +370,7 @@ namespace Serein.Workbench.Views
if (TryPlaceNodeInRegion(nodeControl, position, out var regionControl)) // 判断添加到区域容器
{
// 通知运行环境调用加载节点子项的方法
- flowEnvironment.PlaceNodeToContainer(Guid,
+ flowEnvironment.FlowEdit.PlaceNodeToContainer(Guid,
nodeControl.ViewModel.NodeModel.Guid, // 待移动的节点
regionControl.ViewModel.NodeModel.Guid); // 目标的容器节点
return;
@@ -557,14 +557,14 @@ namespace Serein.Workbench.Views
if (keyEventService.GetKeyState(Key.LeftCtrl) || keyEventService.GetKeyState(Key.RightCtrl))
{
// Ctrl + F5 调试当前流程
- _ = flowEnvironment.StartFlowAsync([flowNodeService.CurrentSelectCanvas.Guid]);
+ _ = flowEnvironment.FlowControl.StartFlowAsync([flowNodeService.CurrentSelectCanvas.Guid]);
}
else if (selectNodeControls.Count == 1 )
{
// F5 调试当前选定节点
var nodeModel = selectNodeControls[0].ViewModel.NodeModel;
SereinEnv.WriteLine(InfoType.INFO, $"调试运行当前节点:{nodeModel.Guid}");
- _ = flowEnvironment.StartFlowFromSelectNodeAsync(nodeModel.Guid);
+ _ = flowEnvironment.FlowControl.StartFlowFromSelectNodeAsync(nodeModel.Guid);
//_ = nodeModel.StartFlowAsync(new DynamicContext(flowEnvironment), new CancellationToken());
}
@@ -897,7 +897,7 @@ namespace Serein.Workbench.Views
{
var canvasGuid = this.Guid;
- flowEnvironment.ConnectInvokeNode(
+ flowEnvironment.FlowEdit.ConnectInvokeNode(
canvasGuid,
cd.StartJunction.MyNode.Guid,
cd.CurrentJunction.MyNode.Guid,
@@ -921,7 +921,7 @@ namespace Serein.Workbench.Views
}
var canvasGuid = this.Guid;
- flowEnvironment.ConnectArgSourceNode(
+ flowEnvironment.FlowEdit.ConnectArgSourceNode(
canvasGuid,
cd.StartJunction.MyNode.Guid,
cd.CurrentJunction.MyNode.Guid,
@@ -1268,7 +1268,7 @@ namespace Serein.Workbench.Views
if (!string.IsNullOrEmpty(guid))
{
var canvasGuid = this.Guid;
- flowEnvironment.RemoveNode(canvasGuid, guid);
+ flowEnvironment.FlowEdit.RemoveNode(canvasGuid, guid);
}
}
}
@@ -1464,13 +1464,13 @@ namespace Serein.Workbench.Views
{
if (menuItem.Header.ToString() == "启动触发器")
{
- flowEnvironment.ActivateFlipflopNode(nodeGuid);
+ flowEnvironment.FlowControl.ActivateFlipflopNode(nodeGuid);
menuItem.Header = "终结触发器";
}
else
{
- flowEnvironment.TerminateFlipflopNode(nodeGuid);
+ flowEnvironment.FlowControl.TerminateFlipflopNode(nodeGuid);
menuItem.Header = "启动触发器";
}
@@ -1490,10 +1490,10 @@ namespace Serein.Workbench.Views
- contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("设为起点", (s, e) => flowEnvironment.SetStartNode(canvasGuid, nodeGuid)));
+ contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("设为起点", (s, e) => flowEnvironment.FlowEdit.SetStartNode(canvasGuid, nodeGuid)));
contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("删除", async (s, e) =>
{
- flowEnvironment.RemoveNode(canvasGuid, nodeGuid);
+ flowEnvironment.FlowEdit.RemoveNode(canvasGuid, nodeGuid);
}));
#region 右键菜单功能 - 控件对齐
diff --git a/Workbench/Views/ViewCanvasInfoView.xaml.cs b/Workbench/Views/ViewCanvasInfoView.xaml.cs
index 1016f8c..739067b 100644
--- a/Workbench/Views/ViewCanvasInfoView.xaml.cs
+++ b/Workbench/Views/ViewCanvasInfoView.xaml.cs
@@ -39,7 +39,7 @@ namespace Serein.Workbench.Views
if (sender is Grid grid && grid.DataContext is IFlowNode nodeModel)
{
NodeInfoViewModel.ViewNodeModel = nodeModel;
- App.GetService().NodeLocate(nodeModel.Guid);
+ App.GetService().FlowEdit.NodeLocate(nodeModel.Guid);
}
// 定位节点