mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-02 14:36:33 +08:00
流程返回值改为FlowResult,记录节点信息、上下文信息,为以后的流程调用回溯做准备
This commit is contained in:
@@ -392,7 +392,7 @@ namespace Serein.NodeFlow.Env
|
||||
IOC.Reset();
|
||||
IOC.Register<IScriptFlowApi, ScriptFlowApi>(); // 注册脚本接口
|
||||
|
||||
var flowTaskOptions = new FlowTaskLibrary
|
||||
var flowTaskOptions = new FlowWorkLibrary
|
||||
{
|
||||
|
||||
Environment = this,
|
||||
@@ -440,8 +440,8 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
if (true || FlowState == RunState.Running || FlipFlopState == RunState.Running)
|
||||
{
|
||||
NodeModelBase? nodeModel = GuidToModel(startNodeGuid);
|
||||
if (nodeModel is null || nodeModel is SingleFlipflopNode)
|
||||
|
||||
if (!TryGetNodeModel(startNodeGuid,out var nodeModel) || nodeModel is SingleFlipflopNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -460,14 +460,14 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/*/// <summary>
|
||||
/// 单独运行一个节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<object> InvokeNodeAsync(IDynamicContext context, string nodeGuid)
|
||||
{
|
||||
object result = new Unit();
|
||||
object result = Unit.Default;
|
||||
if (this.NodeModels.TryGetValue(nodeGuid, out var model))
|
||||
{
|
||||
CancellationTokenSource cts = new CancellationTokenSource();
|
||||
@@ -475,7 +475,7 @@ namespace Serein.NodeFlow.Env
|
||||
cts?.Cancel();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// 结束流程
|
||||
@@ -496,7 +496,10 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="nodeGuid"></param>
|
||||
public void ActivateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
if(!TryGetNodeModel(nodeGuid, out var nodeModel))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (nodeModel is null) return;
|
||||
if (flowTaskManagement is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
|
||||
{
|
||||
@@ -515,7 +518,10 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="nodeGuid"></param>
|
||||
public void TerminateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
if(!TryGetNodeModel(nodeGuid, out var nodeModel))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (nodeModel is null) return;
|
||||
if (flowTaskManagement is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
|
||||
{
|
||||
@@ -858,7 +864,10 @@ namespace Serein.NodeFlow.Env
|
||||
#region 确定节点之间的方法调用关系
|
||||
foreach (var nodeInfo in nodeInfos)
|
||||
{
|
||||
var fromNodeModel = GuidToModel(nodeInfo.Guid);
|
||||
if (!TryGetNodeModel(nodeInfo.Guid, out var fromNodeModel))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (fromNodeModel is null) continue;
|
||||
List<(ConnectionInvokeType connectionType, string[] guids)> allToNodes = [(ConnectionInvokeType.IsSucceed,nodeInfo.TrueNodes),
|
||||
(ConnectionInvokeType.IsFail, nodeInfo.FalseNodes),
|
||||
@@ -869,7 +878,10 @@ namespace Serein.NodeFlow.Env
|
||||
// 遍历当前类型分支的节点(确认连接关系)
|
||||
foreach (var toNodeGuid in item.toNodeGuids)
|
||||
{
|
||||
var toNodeModel = GuidToModel(toNodeGuid);
|
||||
if (!TryGetNodeModel(toNodeGuid, out var toNodeModel))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (toNodeModel is null) {
|
||||
// 防御性代码,加载正常保存的项目文件不会进入这里
|
||||
continue;
|
||||
@@ -915,7 +927,7 @@ namespace Serein.NodeFlow.Env
|
||||
&& NodeModels.TryGetValue(pd.ArgDataSourceNodeGuid, out var fromNode))
|
||||
{
|
||||
|
||||
_ = ConnectArgSourceOfNodeAsync(fromNode, toNode, pd.ArgDataSourceType, pd.Index);
|
||||
await ConnectArgSourceOfNodeAsync(fromNode, toNode, pd.ArgDataSourceType, pd.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -981,20 +993,24 @@ namespace Serein.NodeFlow.Env
|
||||
/// 将节点放置在容器中
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid)
|
||||
public Task<bool> PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid)
|
||||
{
|
||||
// 获取目标节点与容器节点
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
if (nodeModel is null ) return false;
|
||||
|
||||
if(nodeModel.ContainerNode is INodeContainer tmpContainer)
|
||||
if (!TryGetNodeModel(nodeGuid, out var nodeModel))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
if (nodeModel.ContainerNode is INodeContainer tmpContainer)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"节点放置失败,节点[{nodeGuid}]已经放置于容器节点[{((NodeModelBase)tmpContainer).Guid}]");
|
||||
return false;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
var containerNode = GuidToModel(containerNodeGuid); // 获取容器节点
|
||||
if (containerNode is not INodeContainer nodeContainer) return false;
|
||||
if (!TryGetNodeModel(containerNodeGuid, out var containerNode))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
if (containerNode is not INodeContainer nodeContainer) return Task.FromResult(false);
|
||||
|
||||
var result = nodeContainer.PlaceNode(nodeModel); // 放置在容器节点
|
||||
if (result)
|
||||
@@ -1004,7 +1020,7 @@ namespace Serein.NodeFlow.Env
|
||||
OnNodePlace?.Invoke(new NodePlaceEventArgs(nodeGuid, containerNodeGuid)); // 通知UI更改节点放置位置
|
||||
});
|
||||
}
|
||||
return result;
|
||||
return Task.FromResult(result);
|
||||
|
||||
}
|
||||
|
||||
@@ -1012,15 +1028,16 @@ namespace Serein.NodeFlow.Env
|
||||
/// 将节点从容器节点中脱离
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> TakeOutNodeToContainerAsync(string nodeGuid)
|
||||
public Task<bool> TakeOutNodeToContainerAsync(string nodeGuid)
|
||||
{
|
||||
// 获取目标节点与容器节点
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
if (nodeModel is null) return false;
|
||||
|
||||
if(nodeModel.ContainerNode is not INodeContainer nodeContainer)
|
||||
if (!TryGetNodeModel(nodeGuid, out var nodeModel))
|
||||
{
|
||||
return false;
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
if (nodeModel.ContainerNode is not INodeContainer nodeContainer)
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
var result = nodeContainer.TakeOutNode(nodeModel); // 从容器节点取出
|
||||
if (result)
|
||||
@@ -1030,7 +1047,7 @@ namespace Serein.NodeFlow.Env
|
||||
OnNodeTakeOut?.Invoke(new NodeTakeOutEventArgs(nodeGuid)); // 重新放置在画布上
|
||||
});
|
||||
}
|
||||
return result;
|
||||
return Task.FromResult(result);
|
||||
|
||||
|
||||
}
|
||||
@@ -1044,9 +1061,10 @@ namespace Serein.NodeFlow.Env
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<bool> RemoveNodeAsync(string nodeGuid)
|
||||
{
|
||||
var remoteNode = GuidToModel(nodeGuid);
|
||||
if (remoteNode is null)
|
||||
return false;
|
||||
if (!TryGetNodeModel(nodeGuid, out var remoteNode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (remoteNode is SingleFlipflopNode flipflopNode)
|
||||
{
|
||||
@@ -1103,7 +1121,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="fromNodeJunctionType">起始节点控制点</param>
|
||||
/// <param name="toNodeJunctionType">目标节点控制点</param>
|
||||
/// <param name="invokeType">连接关系</param>
|
||||
public async Task<bool> ConnectInvokeNodeAsync(string fromNodeGuid,
|
||||
public Task<bool> ConnectInvokeNodeAsync(string fromNodeGuid,
|
||||
string toNodeGuid,
|
||||
JunctionType fromNodeJunctionType,
|
||||
JunctionType toNodeJunctionType,
|
||||
@@ -1111,17 +1129,19 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
|
||||
// 获取起始节点与目标节点
|
||||
var fromNode = GuidToModel(fromNodeGuid);
|
||||
var toNode = GuidToModel(toNodeGuid);
|
||||
if (fromNode is null || toNode is null) return false;
|
||||
if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
if (fromNode is null || toNode is null) return Task.FromResult(false);
|
||||
(var type, var state) = CheckConnect(fromNode, toNode, fromNodeJunctionType, toNodeJunctionType);
|
||||
if (!state)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.WARN, "出现非预期的连接行为");
|
||||
return false; // 出现不符预期的连接行为,忽略此次连接行为
|
||||
return Task.FromResult(false); // 出现不符预期的连接行为,忽略此次连接行为
|
||||
}
|
||||
|
||||
|
||||
if(type == JunctionOfConnectionType.Invoke)
|
||||
{
|
||||
if (fromNodeJunctionType == JunctionType.Execute)
|
||||
@@ -1132,7 +1152,7 @@ namespace Serein.NodeFlow.Env
|
||||
// 从起始节点“下一个方法”控制点,连接到目标节点“方法调用”控制点
|
||||
state = ConnectInvokeOfNode(fromNode, toNode, invokeType); // 本地环境进行连接
|
||||
}
|
||||
return state;
|
||||
return Task.FromResult(state);
|
||||
|
||||
}
|
||||
|
||||
@@ -1147,8 +1167,10 @@ namespace Serein.NodeFlow.Env
|
||||
public Task<bool> SetConnectPriorityInvoke(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
||||
{
|
||||
// 获取起始节点与目标节点
|
||||
var fromNode = GuidToModel(fromNodeGuid);
|
||||
var toNode = GuidToModel(toNodeGuid);
|
||||
if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
if (fromNode is null || toNode is null) return Task.FromResult(false);
|
||||
if ( fromNode.SuccessorNodes.TryGetValue(connectionType, out var nodes))
|
||||
{
|
||||
@@ -1173,8 +1195,10 @@ namespace Serein.NodeFlow.Env
|
||||
public async Task<bool> RemoveConnectInvokeAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
||||
{
|
||||
// 获取起始节点与目标节点
|
||||
var fromNode = GuidToModel(fromNodeGuid);
|
||||
var toNode = GuidToModel(toNodeGuid);
|
||||
if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (fromNode is null || toNode is null) return false;
|
||||
|
||||
var result = await RemoteConnectAsync(fromNode, toNode, connectionType);
|
||||
@@ -1200,8 +1224,10 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
|
||||
// 获取起始节点与目标节点
|
||||
var fromNode = GuidToModel(fromNodeGuid);
|
||||
var toNode = GuidToModel(toNodeGuid);
|
||||
if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (fromNode is null || toNode is null) return false;
|
||||
(var type, var state) = CheckConnect(fromNode, toNode, fromNodeJunctionType, toNodeJunctionType);
|
||||
if (!state)
|
||||
@@ -1236,8 +1262,10 @@ namespace Serein.NodeFlow.Env
|
||||
public async Task<bool> RemoveConnectArgSourceAsync(string fromNodeGuid, string toNodeGuid, int argIndex)
|
||||
{
|
||||
// 获取起始节点与目标节点
|
||||
var fromNode = GuidToModel(fromNodeGuid);
|
||||
var toNode = GuidToModel(toNodeGuid);
|
||||
if (!TryGetNodeModel(fromNodeGuid, out var fromNode) || !TryGetNodeModel(toNodeGuid, out var toNode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (fromNode is null || toNode is null) return false;
|
||||
var result = await RemoteConnectAsync(fromNode, toNode, argIndex);
|
||||
return result;
|
||||
@@ -1302,10 +1330,11 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="y"></param>
|
||||
public void MoveNode(string nodeGuid, double x, double y)
|
||||
{
|
||||
NodeModelBase? nodeModel = GuidToModel(nodeGuid);
|
||||
if (nodeModel is null) return;
|
||||
if (!TryGetNodeModel(nodeGuid, out var nodeModel))
|
||||
{
|
||||
return;
|
||||
}
|
||||
nodeModel.Position.X = x;
|
||||
|
||||
nodeModel.Position.Y = y;
|
||||
UIContextOperation?.Invoke(() => OnNodeMoved?.Invoke(new NodeMovedEventArgs(nodeGuid, x, y)));
|
||||
|
||||
@@ -1317,9 +1346,10 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="newNodeGuid"></param>
|
||||
public Task<string> SetStartNodeAsync(string newNodeGuid)
|
||||
{
|
||||
var newStartNodeModel = GuidToModel(newNodeGuid);
|
||||
if (newStartNodeModel is null)
|
||||
return Task.FromResult(StartNode?.Guid ?? string.Empty);
|
||||
if (!TryGetNodeModel(newNodeGuid, out var newStartNodeModel))
|
||||
{
|
||||
return Task.FromResult(StartNode?.Guid ?? string.Empty);
|
||||
}
|
||||
SetStartNode(newStartNodeModel);
|
||||
return Task.FromResult(StartNode?.Guid ?? string.Empty);
|
||||
}
|
||||
@@ -1370,12 +1400,13 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="path">属性路径</param>
|
||||
/// <param name="value">变化后的属性值</param>
|
||||
/// <returns></returns>
|
||||
public async Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
|
||||
public Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
|
||||
{
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
if (nodeModel is null) return;
|
||||
SerinExpressionEvaluator.Evaluate($"@Set .{path} = {value}", nodeModel, out _); // 更改对应的数据
|
||||
|
||||
if (TryGetNodeModel(nodeGuid, out var nodeModel))
|
||||
{
|
||||
SerinExpressionEvaluator.Evaluate($"@Set .{path} = {value}", nodeModel, out _); // 更改对应的数据
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
//if (NodeValueChangeLogger.Remove((nodeGuid, path, value)))
|
||||
//{
|
||||
// // 说明存在过重复的修改
|
||||
@@ -1414,7 +1445,10 @@ namespace Serein.NodeFlow.Env
|
||||
/// <returns></returns>
|
||||
public Task<bool> ChangeParameter(string nodeGuid, bool isAdd, int paramIndex)
|
||||
{
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
if (!TryGetNodeModel(nodeGuid, out var nodeModel))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
if (nodeModel is null) return Task.FromResult(false);
|
||||
bool isPass;
|
||||
if (isAdd)
|
||||
@@ -1429,30 +1463,26 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid 转 NodeModel
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <returns>节点Model</returns>
|
||||
/// <exception cref="ArgumentNullException">无法获取节点、Guid/节点为null时报错</exception>
|
||||
private NodeModelBase? GuidToModel(string nodeGuid)
|
||||
public bool TryGetNodeModel(string nodeGuid,out NodeModelBase nodeModel)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nodeGuid))
|
||||
{
|
||||
//throw new ArgumentNullException("not contains - Guid没有对应节点:" + (nodeGuid));
|
||||
return null;
|
||||
nodeModel = null;
|
||||
return false;
|
||||
}
|
||||
if (!NodeModels.TryGetValue(nodeGuid, out NodeModelBase? nodeModel) || nodeModel is null)
|
||||
{
|
||||
//throw new ArgumentNullException("null - Guid存在对应节点,但节点为null:" + (nodeGuid));
|
||||
return null;
|
||||
}
|
||||
return nodeModel;
|
||||
return NodeModels.TryGetValue(nodeGuid, out nodeModel) && nodeModel is not null;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region 流程依赖类库的接口
|
||||
|
||||
|
||||
@@ -492,10 +492,7 @@ namespace Serein.NodeFlow.Env
|
||||
return await currentFlowEnvironment.StartAsyncInSelectNode(startNodeGuid);
|
||||
}
|
||||
|
||||
public async Task<object> InvokeNodeAsync(IDynamicContext context, string nodeGuid)
|
||||
{
|
||||
return await currentFlowEnvironment.InvokeNodeAsync(context, nodeGuid);
|
||||
}
|
||||
|
||||
|
||||
public async Task StartRemoteServerAsync(int port = 7525)
|
||||
{
|
||||
@@ -524,6 +521,11 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
currentFlowEnvironment.SetUIContextOperation(uiContextOperation);
|
||||
}
|
||||
|
||||
public bool TryGetNodeModel(string nodeGuid, out NodeModelBase nodeModel)
|
||||
{
|
||||
return currentFlowEnvironment.TryGetNodeModel(nodeGuid, out nodeModel);
|
||||
}
|
||||
public bool TryGetDelegateDetails(string libraryName, string methodName, out DelegateDetails del)
|
||||
{
|
||||
return currentFlowEnvironment.TryGetDelegateDetails(libraryName, methodName, out del);
|
||||
|
||||
@@ -1217,14 +1217,13 @@ namespace Serein.NodeFlow.Env
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:SetMonitorObjState");
|
||||
}
|
||||
|
||||
public async Task<object> InvokeNodeAsync(IDynamicContext context, string nodeGuid)
|
||||
{
|
||||
// 登录到远程环境后,启动器相关方法无效
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现接口 InvokeNodeAsync");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public bool TryGetNodeModel(string nodeGuid, out NodeModelBase nodeModel)
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:TryGetNodeModel");
|
||||
nodeModel = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetMethodDetailsInfo(string libraryName, string methodName, out MethodDetailsInfo mdInfo)
|
||||
{
|
||||
|
||||
@@ -9,8 +9,10 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow
|
||||
{
|
||||
|
||||
public class FlowTaskLibrary()
|
||||
/// <summary>
|
||||
/// 节点任务执行依赖
|
||||
/// </summary>
|
||||
public class FlowWorkLibrary()
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程运行环境
|
||||
@@ -30,13 +30,13 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 初始化选项
|
||||
/// </summary>
|
||||
public FlowTaskLibrary WorkLibrary { get; }
|
||||
public FlowWorkLibrary WorkLibrary { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 流程任务管理
|
||||
/// </summary>
|
||||
/// <param name="library"></param>
|
||||
public FlowWorkManagement(FlowTaskLibrary library)
|
||||
public FlowWorkManagement(FlowWorkLibrary library)
|
||||
{
|
||||
WorkLibrary = library;
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace Serein.NodeFlow
|
||||
{
|
||||
var context = pool.Allocate(); // 启动全局触发器时新建上下文
|
||||
var newFlowData = await singleFlipFlopNode.ExecutingAsync(context, singleToken); // 获取触发器等待Task
|
||||
context.AddOrUpdate(singleFlipFlopNode.Guid, newFlowData);
|
||||
context.AddOrUpdate(singleFlipFlopNode, newFlowData);
|
||||
if (context.NextOrientation == ConnectionInvokeType.None)
|
||||
{
|
||||
continue;
|
||||
@@ -326,6 +326,14 @@ namespace Serein.NodeFlow
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全局触发器触发后的调用
|
||||
/// </summary>
|
||||
/// <param name="singleFlipFlopNode"></param>
|
||||
/// <param name="singleToken"></param>
|
||||
/// <param name="pool"></param>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
private static async Task? CallSubsequentNode(SingleFlipflopNode singleFlipFlopNode, CancellationToken singleToken, ObjectPool<IDynamicContext> pool, IDynamicContext context)
|
||||
{
|
||||
var flowState = context.NextOrientation; // 记录一下流程状态
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Serein.NodeFlow.Model
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<object?> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -45,7 +45,7 @@ namespace Serein.NodeFlow.Model
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
return null;
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
var state = await node.ExecutingAsync(context, token);
|
||||
if (context.NextOrientation != ConnectionInvokeType.IsSucceed)
|
||||
@@ -56,7 +56,8 @@ namespace Serein.NodeFlow.Model
|
||||
}
|
||||
|
||||
//var previousNode = context.GetPreviousNode()
|
||||
return context.TransmissionData(this); // 条件区域透传上一节点的数据
|
||||
var result = context.TransmissionData(this); // 条件区域透传上一节点的数据
|
||||
return new FlowResult(this,context, result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -110,9 +110,12 @@ namespace Serein.NodeFlow.Model
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<object?> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
if (token.IsCancellationRequested) return null;
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
// 接收上一节点参数or自定义参数内容
|
||||
object? parameter;
|
||||
object? result = null;
|
||||
@@ -121,17 +124,31 @@ namespace Serein.NodeFlow.Model
|
||||
{
|
||||
// 使用自动取参
|
||||
var pd = MethodDetails.ParameterDetailss[INDEX_EXPRESSION];
|
||||
var hasNode = context.Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var argSourceNode);
|
||||
if (hasNode)
|
||||
{
|
||||
context.NextOrientation = ConnectionInvokeType.IsError;
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
if (hasNode)
|
||||
{
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
|
||||
{
|
||||
result = context.GetFlowData(pd.ArgDataSourceNodeGuid); // 使用自定义节点的参数
|
||||
result = context.GetFlowData(argSourceNode).Value; // 使用自定义节点的参数
|
||||
}
|
||||
else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
|
||||
{
|
||||
result = await Env.InvokeNodeAsync(context, pd.ArgDataSourceNodeGuid); // 立刻调用目标节点,然后使用其返回值
|
||||
CancellationTokenSource cts = new CancellationTokenSource();
|
||||
var nodeResult = await argSourceNode.ExecutingAsync(context, cts.Token);
|
||||
result = nodeResult.Value;
|
||||
cts?.Cancel();
|
||||
cts?.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = context.TransmissionData(this); // 条件节点透传上一节点的数据
|
||||
result = context.TransmissionData(this).Value; // 条件节点透传上一节点的数据
|
||||
}
|
||||
parameter = result; // 使用上一节点的参数
|
||||
|
||||
@@ -167,7 +184,7 @@ namespace Serein.NodeFlow.Model
|
||||
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"{result} {Expression} -> " + context.NextOrientation);
|
||||
//return result;
|
||||
return judgmentResult;
|
||||
return new FlowResult(this, context, judgmentResult);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -92,22 +92,32 @@ namespace Serein.NodeFlow.Model
|
||||
}
|
||||
|
||||
|
||||
public override async Task<object?> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
if(token.IsCancellationRequested) return null;
|
||||
if(token.IsCancellationRequested) return new FlowResult(this, context);
|
||||
|
||||
object? parameter = null;// context.TransmissionData(this); // 表达式节点使用上一节点数据
|
||||
var pd = MethodDetails.ParameterDetailss[0];
|
||||
|
||||
var hasNode = context.Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var argSourceNode);
|
||||
if (hasNode)
|
||||
{
|
||||
context.NextOrientation = ConnectionInvokeType.IsError;
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
|
||||
{
|
||||
// 使用自定义节点的参数
|
||||
parameter = context.GetFlowData(pd.ArgDataSourceNodeGuid);
|
||||
parameter = context.GetFlowData(argSourceNode).Value;
|
||||
}
|
||||
else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
|
||||
{
|
||||
// 立刻调用目标节点,然后使用其返回值
|
||||
parameter = await Env.InvokeNodeAsync(context, pd.ArgDataSourceNodeGuid);
|
||||
var cts = new CancellationTokenSource();
|
||||
var result = await argSourceNode.ExecutingAsync(context, cts.Token);
|
||||
cts?.Cancel();
|
||||
cts?.Dispose();
|
||||
parameter = result.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -129,13 +139,13 @@ namespace Serein.NodeFlow.Model
|
||||
}
|
||||
|
||||
context.NextOrientation = ConnectionInvokeType.IsSucceed;
|
||||
return result;
|
||||
return new FlowResult(this,context, result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.NextOrientation = ConnectionInvokeType.IsError;
|
||||
context.ExceptionOfRuning = ex;
|
||||
return parameter;
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Serein.NodeFlow.Model
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public override async Task<object?> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
#region 执行前中断
|
||||
if (DebugSetting.IsInterrupt) // 执行触发前
|
||||
@@ -40,8 +40,13 @@ namespace Serein.NodeFlow.Model
|
||||
}
|
||||
|
||||
var instance = context.Env.IOC.Get(md.ActingInstanceType);
|
||||
if (instance is null)
|
||||
{
|
||||
Env.IOC.Register(md.ActingInstanceType).Build();
|
||||
instance = Env.IOC.Get(md.ActingInstanceType);
|
||||
}
|
||||
await dd.InvokeAsync(instance, [context]);
|
||||
var args = await GetParametersAsync(context, token);
|
||||
var args = await this.GetParametersAsync(context, token);
|
||||
// 因为这里会返回不确定的泛型 IFlipflopContext<TRsult>
|
||||
// 而我们只需要获取到 State 和 Value(返回的数据)
|
||||
// 所以使用 dynamic 类型接收
|
||||
@@ -58,7 +63,9 @@ namespace Serein.NodeFlow.Model
|
||||
{
|
||||
throw new FlipflopException(base.MethodDetails.MethodName + "触发器超时触发。Guid" + base.Guid);
|
||||
}
|
||||
return dynamicFlipflopContext.Value;
|
||||
object result = dynamicFlipflopContext.Value;
|
||||
var flowReslt = new FlowResult(this, context, result);
|
||||
return flowReslt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -115,33 +115,34 @@ namespace Serein.NodeFlow.Model
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<object?> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
if (token.IsCancellationRequested) return null;
|
||||
if (token.IsCancellationRequested) return new FlowResult(this, context);
|
||||
if (string.IsNullOrEmpty(KeyName))
|
||||
{
|
||||
context.NextOrientation = ConnectionInvokeType.IsError;
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"全局数据的KeyName不能为空[{this.Guid}]");
|
||||
return null;
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
if (DataNode is null)
|
||||
{
|
||||
context.NextOrientation = ConnectionInvokeType.IsError;
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"全局数据节点没有设置数据来源[{this.Guid}]");
|
||||
return null;
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await context.Env.InvokeNodeAsync(context, DataNode.Guid);
|
||||
SereinEnv.AddOrUpdateFlowGlobalData(KeyName, result);
|
||||
|
||||
var result = await DataNode.ExecutingAsync(context, token);
|
||||
SereinEnv.AddOrUpdateFlowGlobalData(KeyName, result.Value);
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.NextOrientation = ConnectionInvokeType.IsError;
|
||||
context.ExceptionOfRuning = ex;
|
||||
return null;
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -165,12 +165,11 @@ namespace Serein.NodeFlow.Model
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<object?> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
if(token.IsCancellationRequested) return null;
|
||||
var @params = await GetParametersAsync(context, token);
|
||||
if(token.IsCancellationRequested) return null;
|
||||
|
||||
if (token.IsCancellationRequested) return new FlowResult(this, context);
|
||||
var @params = await this.GetParametersAsync(context, token);
|
||||
if(token.IsCancellationRequested) return new FlowResult(this, context);
|
||||
|
||||
//context.AddOrUpdate($"{context.Guid}_{this.Guid}_Params", @params[0]); // 后面再改
|
||||
ReloadScript();// 每次都重新解析
|
||||
@@ -199,9 +198,9 @@ namespace Serein.NodeFlow.Model
|
||||
if (token.IsCancellationRequested) return null;
|
||||
|
||||
var result = await ScriptInterpreter.InterpretAsync(scriptContext, mainNode); // 从入口节点执行
|
||||
envEvent.OnFlowRunComplete -= onFlowStop;
|
||||
envEvent.OnFlowRunComplete -= onFlowStop;
|
||||
return new FlowResult(this, context, result);
|
||||
//SereinEnv.WriteLine(InfoType.INFO, "FlowContext Guid : " + context.Guid);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@ namespace Serein.NodeFlow.Model
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<object?> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
if (token.IsCancellationRequested) return null;
|
||||
if (token.IsCancellationRequested) return new FlowResult(this,context);
|
||||
if(Adapter is null)
|
||||
{
|
||||
|
||||
var result = await base.ExecutingAsync(context, token);
|
||||
if (result is IEmbeddedContent adapter)
|
||||
if (result.Value is IEmbeddedContent adapter)
|
||||
{
|
||||
this.Adapter = adapter;
|
||||
context.NextOrientation = ConnectionInvokeType.IsSucceed;
|
||||
@@ -35,12 +35,12 @@ namespace Serein.NodeFlow.Model
|
||||
else
|
||||
{
|
||||
var p = context.GetPreviousNode(this);
|
||||
var data = context.GetFlowData(p.Guid);
|
||||
var data = context.GetFlowData(p).Value;
|
||||
var iflowContorl = Adapter.GetFlowControl();
|
||||
iflowContorl.OnExecuting(data);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
return new FlowResult(this, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,22 +42,21 @@ namespace Serein.NodeFlow
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object? GetArgData(IDynamicContext context, int index)
|
||||
{
|
||||
var _paramsKey = $"{context?.Guid}_{NodeModel.Guid}_Params";
|
||||
var obj = context?.GetFlowData(_paramsKey);
|
||||
if (obj is object[] @params && index < @params.Length)
|
||||
{
|
||||
return @params[index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//public object? GetArgData(IDynamicContext context, int index)
|
||||
//{
|
||||
// var _paramsKey = $"{context?.Guid}_{NodeModel.Guid}_Params";
|
||||
// var obj = context?.GetFlowData(_paramsKey);
|
||||
// if (obj is object[] @params && index < @params.Length)
|
||||
// {
|
||||
// return @params[index];
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
|
||||
|
||||
public object? GetFlowData(IDynamicContext context)
|
||||
{
|
||||
return context?.GetFlowData(NodeModel.Guid);
|
||||
}
|
||||
//public object? GetFlowData(IDynamicContext context)
|
||||
//{
|
||||
// return context?.GetFlowData(NodeModel.Guid);
|
||||
//}
|
||||
|
||||
public object? GetGlobalData(string keyName)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user