mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-05 15:56:33 +08:00
1. 重新设计了Generate项目及相关特性的命名,避免与其他类型混淆。
2. 补充了部分注释。 3. 修改了删除容器节点时,容器内子节点未正确删除的问题。
This commit is contained in:
@@ -57,9 +57,18 @@ namespace Serein.Library
|
||||
CollectionSetter
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示方法的类型
|
||||
/// </summary>
|
||||
public enum GSType
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取值
|
||||
/// </summary>
|
||||
Get,
|
||||
/// <summary>
|
||||
/// 设置值
|
||||
/// </summary>
|
||||
Set,
|
||||
}
|
||||
|
||||
@@ -149,7 +158,7 @@ namespace Serein.Library
|
||||
/// 目前提供了创建集合取值/赋值委托
|
||||
/// </summary>
|
||||
/// <param name="type">类型信息</param>
|
||||
/// <param name="gsType">操作类型</param>
|
||||
/// <param name="emitType">操作类型</param>
|
||||
public DelegateDetails(Type type, EmitType emitType)
|
||||
{
|
||||
if (emitType == EmitType.CollectionSetter)
|
||||
|
||||
@@ -5,6 +5,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// FlipflopFunc 类提供了与 Flipflop 相关的功能方法。
|
||||
/// </summary>
|
||||
public static class FlipflopFunc
|
||||
{
|
||||
/// <summary>
|
||||
@@ -72,15 +75,34 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public class FlipflopContext<TResult> : IFlipflopContext<TResult>
|
||||
{
|
||||
/// <summary>
|
||||
/// 触发器完成的状态(根据业务场景手动设置)
|
||||
/// </summary>
|
||||
public FlipflopStateType State { get; set; }
|
||||
/// <summary>
|
||||
/// 触发类型
|
||||
/// </summary>
|
||||
|
||||
public TriggerDescription Type { get; set; }
|
||||
/// <summary>
|
||||
/// 触发时传递的数据
|
||||
/// </summary>
|
||||
public TResult Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发器上下文构造函数
|
||||
/// </summary>
|
||||
/// <param name="ffState"></param>
|
||||
public FlipflopContext(FlipflopStateType ffState)
|
||||
{
|
||||
State = ffState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发器上下文构造函数,传入状态和数据值
|
||||
/// </summary>
|
||||
/// <param name="ffState"></param>
|
||||
/// <param name="value"></param>
|
||||
public FlipflopContext(FlipflopStateType ffState, TResult value)
|
||||
{
|
||||
State = ffState;
|
||||
|
||||
@@ -16,81 +16,88 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 流程画布
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node)]
|
||||
public partial class FlowCanvasDetails
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程画布的构造函数
|
||||
/// </summary>
|
||||
/// <param name="env"></param>
|
||||
public FlowCanvasDetails(IFlowEnvironment env)
|
||||
{
|
||||
Env = env;
|
||||
}
|
||||
/// <summary>
|
||||
/// 流程画布的运行环境
|
||||
/// </summary>
|
||||
|
||||
public IFlowEnvironment Env { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 画布拥有的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = false)]
|
||||
[DataInfo(IsProtection = false)]
|
||||
private List<IFlowNode> _nodes = [];
|
||||
//private System.Collections.ObjectModel.ObservableCollection<IFlowNode> _nodes = [];
|
||||
|
||||
/// <summary>
|
||||
/// 画布公开的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = false)]
|
||||
[DataInfo(IsProtection = false)]
|
||||
private List<IFlowNode> _publicNodes = [];
|
||||
|
||||
/// <summary>
|
||||
/// 标识画布ID
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = false)]
|
||||
[DataInfo(IsProtection = false)]
|
||||
private string _guid;
|
||||
|
||||
/// <summary>
|
||||
/// 画布名称
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// 画布宽度
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _width;
|
||||
|
||||
/// <summary>
|
||||
/// 画布高度
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _height;
|
||||
|
||||
/// <summary>
|
||||
/// 预览位置X
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _viewX;
|
||||
|
||||
/// <summary>
|
||||
/// 预览位置Y
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _viewY;
|
||||
|
||||
/// <summary>
|
||||
/// 缩放比例X
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _scaleX = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 缩放比例Y
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _scaleY = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private IFlowNode _startNode;
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace Serein.Library
|
||||
/// 动态流程上下文
|
||||
/// </summary>
|
||||
/// <param name="flowEnvironment">脚本运行时的IOC</param>
|
||||
/// <param name="ioc">脚本运行时使用的IOC容器</param>
|
||||
public FlowContext(IFlowEnvironment flowEnvironment)
|
||||
{
|
||||
Env = flowEnvironment;
|
||||
@@ -110,6 +109,10 @@ namespace Serein.Library
|
||||
return flowInvokeInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前流程上下文的所有节点调用信息,包含每个节点的执行时间、调用类型、执行状态等。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<FlowInvokeInfo> GetAllInvokeInfos() => [.. flowInvokeInfos.Values];
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,17 +9,6 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示空数据
|
||||
/// </summary>
|
||||
/*public readonly struct Unit : IEquatable<Unit>
|
||||
{
|
||||
public static readonly Unit Default = default;
|
||||
public bool Equals(Unit _) => true;
|
||||
public override bool Equals(object obj) => obj is Unit;
|
||||
public override int GetHashCode() => 0;
|
||||
}*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程返回值的包装
|
||||
|
||||
@@ -33,6 +33,11 @@ namespace Serein.Library.FlowNode
|
||||
/// </summary>
|
||||
public class JunctionModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 连接点模型构造函数
|
||||
/// </summary>
|
||||
/// <param name="NodeModel"></param>
|
||||
/// <param name="JunctionType"></param>
|
||||
public JunctionModel(IFlowNode NodeModel, JunctionType JunctionType)
|
||||
{
|
||||
Guid = System.Guid.NewGuid().ToString();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -8,76 +7,21 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
/*
|
||||
public class CallNodeLookup : IFlowCallTree
|
||||
{
|
||||
private static readonly string[] _keys = new[]
|
||||
{
|
||||
"Start", // 0
|
||||
"Stop", // 1
|
||||
"Reset", // 2
|
||||
"Pause", // 3
|
||||
"Resume", // 4
|
||||
"Check", // 5
|
||||
"Init", // 6
|
||||
"Load", // 7
|
||||
"Save", // 8
|
||||
"Clear" // 9
|
||||
};
|
||||
|
||||
private static readonly CallNode[] _values = new CallNode[10];
|
||||
|
||||
static CallNodeLookup()
|
||||
{
|
||||
*//*_values[0] = new CallNode("Start");
|
||||
_values[1] = new CallNode("Stop");
|
||||
_values[2] = new CallNode("Reset");
|
||||
_values[3] = new CallNode("Pause");
|
||||
_values[4] = new CallNode("Resume");
|
||||
_values[5] = new CallNode("Check");
|
||||
_values[6] = new CallNode("Init");
|
||||
_values[7] = new CallNode("Load");
|
||||
_values[8] = new CallNode("Save");
|
||||
_values[9] = new CallNode("Clear");*//*
|
||||
}
|
||||
|
||||
// 最小冲突哈希函数(简单示例,固定键集有效)
|
||||
private static int PerfectHash(string key)
|
||||
{
|
||||
return key switch
|
||||
{
|
||||
"Start" => 0,
|
||||
"Stop" => 1,
|
||||
"Reset" => 2,
|
||||
"Pause" => 3,
|
||||
"Resume" => 4,
|
||||
"Check" => 5,
|
||||
"Init" => 6,
|
||||
"Load" => 7,
|
||||
"Save" => 8,
|
||||
"Clear" => 9,
|
||||
_ => -1
|
||||
};
|
||||
}
|
||||
|
||||
public CallNode Get(string key)
|
||||
{
|
||||
int index = PerfectHash(key);
|
||||
if (index >= 0 && _keys[index] == key)
|
||||
return _values[index];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 流程调用树,管理所有的调用节点
|
||||
/// </summary>
|
||||
public class FlowCallTree : IFlowCallTree
|
||||
{
|
||||
|
||||
private readonly SortedDictionary<string, CallNode> _callNodes = new SortedDictionary<string,CallNode>();
|
||||
//private readonly Dictionary<string, CallNode> _callNodes = new Dictionary<string,CallNode>();
|
||||
|
||||
/// <summary>
|
||||
/// 索引器,允许通过字符串索引访问CallNode
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode this[string index]
|
||||
{
|
||||
get
|
||||
@@ -92,17 +36,33 @@ namespace Serein.Library
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个调用节点到流程调用树中
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="action"></param>
|
||||
public void AddCallNode(string nodeGuid, Action<IFlowContext> action)
|
||||
{
|
||||
var node = new CallNode(nodeGuid, action);
|
||||
_callNodes[nodeGuid] = node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个调用节点到流程调用树中,使用异步函数
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="func"></param>
|
||||
public void AddCallNode(string nodeGuid, Func<IFlowContext, Task> func)
|
||||
{
|
||||
var node = new CallNode(nodeGuid, func);
|
||||
_callNodes[nodeGuid] = node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定Key的CallNode,如果不存在则返回null
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode Get(string key)
|
||||
{
|
||||
return _callNodes.TryGetValue(key, out CallNode callNode) ? callNode : null;
|
||||
@@ -112,7 +72,9 @@ namespace Serein.Library
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 调用节点,代表一个流程中的调用点,可以是一个Action或一个异步函数。
|
||||
/// </summary>
|
||||
|
||||
public class CallNode
|
||||
{
|
||||
@@ -120,11 +82,21 @@ namespace Serein.Library
|
||||
private Func<IFlowContext, Task> taskFunc;
|
||||
private Action<IFlowContext> action;
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的调用节点,使用指定的节点Guid。
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public CallNode(string nodeGuid)
|
||||
{
|
||||
Guid = nodeGuid;
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的调用节点,使用指定的节点Guid和Action。
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="action"></param>
|
||||
public CallNode(string nodeGuid, Action<IFlowContext> action)
|
||||
{
|
||||
Guid = nodeGuid;
|
||||
@@ -132,6 +104,11 @@ namespace Serein.Library
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的调用节点,使用指定的节点Guid和异步函数。
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="func"></param>
|
||||
public CallNode(string nodeGuid, Func<IFlowContext, Task> func)
|
||||
{
|
||||
Guid = nodeGuid;
|
||||
@@ -139,7 +116,9 @@ namespace Serein.Library
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化调用节点,设置默认的子节点和后继节点字典。
|
||||
/// </summary>
|
||||
private void Init()
|
||||
{
|
||||
//PreviousNodes = new Dictionary<ConnectionInvokeType, List<CallNode>>();
|
||||
@@ -151,17 +130,28 @@ namespace Serein.Library
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private enum ActionType
|
||||
{
|
||||
Action,
|
||||
Task,
|
||||
}
|
||||
private ActionType actionType = ActionType.Action;
|
||||
|
||||
/// <summary>
|
||||
/// 设置调用节点的Action,表示该节点执行一个同步操作。
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
public void SetAction(Action<IFlowContext> action)
|
||||
{
|
||||
this.action = action;
|
||||
actionType = ActionType.Action;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置调用节点的异步函数,表示该节点执行一个异步操作。
|
||||
/// </summary>
|
||||
/// <param name="taskFunc"></param>
|
||||
public void SetAction(Func<IFlowContext, Task> taskFunc)
|
||||
{
|
||||
this.taskFunc = taskFunc;
|
||||
@@ -173,15 +163,23 @@ namespace Serein.Library
|
||||
/// 对应的节点
|
||||
/// </summary>
|
||||
public string Guid { get; }
|
||||
|
||||
#if false
|
||||
|
||||
/// <summary>
|
||||
/// 不同分支的父节点(流程调用)
|
||||
/// </summary>
|
||||
//public Dictionary<ConnectionInvokeType, List<CallNode>> PreviousNodes { get; private set; }
|
||||
public Dictionary<ConnectionInvokeType, List<CallNode>> PreviousNodes { get; private set; }
|
||||
|
||||
#endif
|
||||
/// <summary>
|
||||
/// 不同分支的子节点(流程调用)
|
||||
/// </summary>
|
||||
public Dictionary<ConnectionInvokeType, List<CallNode>> SuccessorNodes { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点数组,分为四个分支:上游、成功、失败、错误,每个分支最多支持16个子节点。
|
||||
/// </summary>
|
||||
public CallNode[][] ChildNodes { get; private set; } = new CallNode[][]
|
||||
{
|
||||
new CallNode[MaxChildNodeCount],
|
||||
@@ -191,7 +189,12 @@ namespace Serein.Library
|
||||
};
|
||||
private const int MaxChildNodeCount = 16; // 每个分支最多支持16个子节点
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定类型的子节点数量。
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public int GetCount(ConnectionInvokeType type)
|
||||
{
|
||||
if (type == ConnectionInvokeType.Upstream) return UpstreamNodeCount;
|
||||
@@ -201,11 +204,29 @@ namespace Serein.Library
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前节点的子节点数量。
|
||||
/// </summary>
|
||||
public int UpstreamNodeCount { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前节点的成功后继子节点数量。
|
||||
/// </summary>
|
||||
public int IsSuccessorNodeCount { get; private set; } = 0;
|
||||
/// <summary>
|
||||
/// 获取当前节点的失败后继子节点数量。
|
||||
/// </summary>
|
||||
public int IsFailNodeCount { get; private set; } = 0;
|
||||
/// <summary>
|
||||
/// 获取当前节点的错误后继子节点数量。
|
||||
/// </summary>
|
||||
public int IsErrorNodeCount { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个上游子节点到当前节点。
|
||||
/// </summary>
|
||||
/// <param name="callNode"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode AddChildNodeUpstream(CallNode callNode)
|
||||
{
|
||||
var connectionInvokeType = ConnectionInvokeType.Upstream;
|
||||
@@ -214,6 +235,11 @@ namespace Serein.Library
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个成功后继子节点到当前节点。
|
||||
/// </summary>
|
||||
/// <param name="callNode"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode AddChildNodeSucceed(CallNode callNode)
|
||||
{
|
||||
ChildNodes[0][UpstreamNodeCount++] = callNode;
|
||||
@@ -224,6 +250,11 @@ namespace Serein.Library
|
||||
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加一个失败后继子节点到当前节点。
|
||||
/// </summary>
|
||||
/// <param name="callNode"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode AddChildNodeFail(CallNode callNode)
|
||||
{
|
||||
var connectionInvokeType = ConnectionInvokeType.IsFail;
|
||||
@@ -232,6 +263,12 @@ namespace Serein.Library
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个错误后继子节点到当前节点。
|
||||
/// </summary>
|
||||
/// <param name="callNode"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode AddChildNodeError(CallNode callNode)
|
||||
{
|
||||
var connectionInvokeType = ConnectionInvokeType.IsError;
|
||||
@@ -268,7 +305,7 @@ namespace Serein.Library
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly DefaultObjectPool<Stack<CallNode>> _stackPool = new DefaultObjectPool<Stack<CallNode>>(new DefaultPooledObjectPolicy<Stack<CallNode>>());
|
||||
private static readonly ObjectPool<Stack<CallNode>> _stackPool = new ObjectPool<Stack<CallNode>>(() => new Stack<CallNode>());
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -279,7 +316,7 @@ namespace Serein.Library
|
||||
/// <returns></returns>
|
||||
public async Task<FlowResult> StartFlowAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
var stack = _stackPool.Get();
|
||||
var stack = _stackPool.Allocate();
|
||||
stack.Push(this);
|
||||
while (true)
|
||||
{
|
||||
@@ -331,7 +368,7 @@ namespace Serein.Library
|
||||
|
||||
if (stack.Count == 0)
|
||||
{
|
||||
_stackPool.Return(stack);
|
||||
_stackPool.Free(stack);
|
||||
flowResult = context.GetFlowData(currentNode.Guid);
|
||||
return flowResult; // 说明流程到了终点
|
||||
}
|
||||
@@ -339,7 +376,7 @@ namespace Serein.Library
|
||||
if (context.RunState == RunState.Completion)
|
||||
{
|
||||
|
||||
_stackPool.Return(stack);
|
||||
_stackPool.Free(stack);
|
||||
context.Env.WriteLine(InfoType.INFO, $"流程执行到节点[{currentNode.Guid}]时提前结束,将返回当前执行结果。");
|
||||
flowResult = context.GetFlowData(currentNode.Guid);
|
||||
return flowResult; // 流程执行完成,返回结果
|
||||
@@ -347,7 +384,7 @@ namespace Serein.Library
|
||||
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
_stackPool.Return(stack);
|
||||
_stackPool.Free(stack);
|
||||
throw new Exception($"流程执行到节点[{currentNode.Guid}]时被取消,未能获取到流程结果。");
|
||||
}
|
||||
|
||||
@@ -359,8 +396,16 @@ namespace Serein.Library
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程调用树接口,提供获取CallNode的方法。
|
||||
/// </summary>
|
||||
public interface IFlowCallTree
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取指定Key的CallNode,如果不存在则返回null。
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
CallNode Get(string key);
|
||||
}
|
||||
|
||||
@@ -371,10 +416,22 @@ namespace Serein.Library
|
||||
{
|
||||
private readonly IFlowCallTree flowCallTree;
|
||||
private readonly IFlowEnvironment flowEnvironment;
|
||||
|
||||
/// <summary>
|
||||
/// 轻量级流程上下文池,使用对象池模式来管理流程上下文的创建和回收。
|
||||
/// </summary>
|
||||
public static Serein.Library.Utils.ObjectPool<IFlowContext> FlowContextPool { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 单例IOC容器,用于依赖注入和服务定位。
|
||||
/// </summary>
|
||||
public ISereinIOC IOC => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// 轻量级流程控制器构造函数,接受流程调用树和流程环境作为参数。
|
||||
/// </summary>
|
||||
/// <param name="flowCallTree"></param>
|
||||
/// <param name="flowEnvironment"></param>
|
||||
public LightweightFlowControl(IFlowCallTree flowCallTree, IFlowEnvironment flowEnvironment)
|
||||
{
|
||||
this.flowCallTree = flowCallTree;
|
||||
@@ -385,11 +442,12 @@ namespace Serein.Library
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<object> InvokeAsync(string apiGuid, Dictionary<string, object> dict)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<TResult> InvokeAsync<TResult>(string apiGuid, Dictionary<string, object> dict)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -398,7 +456,7 @@ namespace Serein.Library
|
||||
|
||||
//private readonly DefaultObjectPool<IDynamicContext> _stackPool = new DefaultObjectPool<IDynamicContext>(new DynamicContext(this));
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<TResult> StartFlowAsync<TResult>(string startNodeGuid)
|
||||
{
|
||||
IFlowContext context = Serein.Library.LightweightFlowControl.FlowContextPool.Allocate();
|
||||
@@ -443,45 +501,48 @@ namespace Serein.Library
|
||||
throw new ArgumentNullException($"类型转换失败,流程返回数据与泛型不匹配,当前返回类型为[{flowResult.Value.GetType().FullName}]。");
|
||||
}
|
||||
}
|
||||
public async Task<bool> StartFlowAsync(string[] canvasGuids)
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<bool> StartFlowAsync(string[] canvasGuids)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<bool> ExitFlowAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#region 无须实现
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ActivateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void TerminateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void UseExternalIOC(ISereinIOC ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void UseExternalIOC(ISereinIOC ioc, Action<ISereinIOC> setDefultMemberOnReset = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -495,110 +556,128 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public class LightweightFlowEnvironmentEvent : IFlowEnvironmentEvent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public event LoadDllHandler DllLoad;
|
||||
/// <inheritdoc/>
|
||||
public event ProjectLoadedHandler ProjectLoaded;
|
||||
/// <inheritdoc/>
|
||||
public event ProjectSavingHandler ProjectSaving;
|
||||
/// <inheritdoc/>
|
||||
public event NodeConnectChangeHandler NodeConnectChanged;
|
||||
/// <inheritdoc/>
|
||||
public event CanvasCreateHandler CanvasCreated;
|
||||
/// <inheritdoc/>
|
||||
public event CanvasRemoveHandler CanvasRemoved;
|
||||
/// <inheritdoc/>
|
||||
public event NodeCreateHandler NodeCreated;
|
||||
/// <inheritdoc/>
|
||||
public event NodeRemoveHandler NodeRemoved;
|
||||
/// <inheritdoc/>
|
||||
public event NodePlaceHandler NodePlace;
|
||||
/// <inheritdoc/>
|
||||
public event NodeTakeOutHandler NodeTakeOut;
|
||||
/// <inheritdoc/>
|
||||
public event StartNodeChangeHandler StartNodeChanged;
|
||||
/// <inheritdoc/>
|
||||
public event FlowRunCompleteHandler FlowRunComplete;
|
||||
/// <inheritdoc/>
|
||||
public event MonitorObjectChangeHandler MonitorObjectChanged;
|
||||
/// <inheritdoc/>
|
||||
public event NodeInterruptStateChangeHandler NodeInterruptStateChanged;
|
||||
/// <inheritdoc/>
|
||||
public event ExpInterruptTriggerHandler InterruptTriggered;
|
||||
/// <inheritdoc/>
|
||||
public event IOCMembersChangedHandler IOCMembersChanged;
|
||||
/// <inheritdoc/>
|
||||
public event NodeLocatedHandler NodeLocated;
|
||||
/// <inheritdoc/>
|
||||
public event EnvOutHandler EnvOutput;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnDllLoad(LoadDllEventArgs eventArgs)
|
||||
{
|
||||
DllLoad?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnProjectLoaded(ProjectLoadedEventArgs eventArgs)
|
||||
{
|
||||
ProjectLoaded?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnProjectSaving(ProjectSavingEventArgs eventArgs)
|
||||
{
|
||||
ProjectSaving?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeConnectChanged(NodeConnectChangeEventArgs eventArgs)
|
||||
{
|
||||
NodeConnectChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCanvasCreated(CanvasCreateEventArgs eventArgs)
|
||||
{
|
||||
CanvasCreated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCanvasRemoved(CanvasRemoveEventArgs eventArgs)
|
||||
{
|
||||
CanvasRemoved?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeCreated(NodeCreateEventArgs eventArgs)
|
||||
{
|
||||
NodeCreated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeRemoved(NodeRemoveEventArgs eventArgs)
|
||||
{
|
||||
NodeRemoved?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodePlace(NodePlaceEventArgs eventArgs)
|
||||
{
|
||||
NodePlace?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeTakeOut(NodeTakeOutEventArgs eventArgs)
|
||||
{
|
||||
NodeTakeOut?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnStartNodeChanged(StartNodeChangeEventArgs eventArgs)
|
||||
{
|
||||
StartNodeChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnFlowRunComplete(FlowEventArgs eventArgs)
|
||||
{
|
||||
FlowRunComplete?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnMonitorObjectChanged(MonitorObjectEventArgs eventArgs)
|
||||
{
|
||||
MonitorObjectChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeInterruptStateChanged(NodeInterruptStateChangeEventArgs eventArgs)
|
||||
{
|
||||
NodeInterruptStateChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnInterruptTriggered(InterruptTriggerEventArgs eventArgs)
|
||||
{
|
||||
InterruptTriggered?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnIOCMembersChanged(IOCMembersChangedEventArgs eventArgs)
|
||||
{
|
||||
IOCMembersChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeLocated(NodeLocatedEventArgs eventArgs)
|
||||
{
|
||||
NodeLocated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnEnvOutput(InfoType type, string value)
|
||||
{
|
||||
EnvOutput?.Invoke(type, value);
|
||||
@@ -611,128 +690,131 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public class LightweightFlowEnvironment : IFlowEnvironment
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 轻量级流程环境构造函数,接受一个流程环境事件接口。
|
||||
/// </summary>
|
||||
/// <param name="lightweightFlowEnvironmentEvent"></param>
|
||||
public LightweightFlowEnvironment(IFlowEnvironmentEvent lightweightFlowEnvironmentEvent)
|
||||
{
|
||||
this.Event = lightweightFlowEnvironmentEvent;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
public void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial)
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ISereinIOC IOC => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowEdit FlowEdit => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowControl FlowControl => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowEnvironmentEvent Event { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string EnvName => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string ProjectFileLocation => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool _IsGlobalInterrupt => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsControlRemoteEnv => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public InfoClass InfoClass { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
/// <inheritdoc/>
|
||||
public RunState FlowState { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowEnvironment CurrentEnv => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UIContextOperation UIContextOperation => throw new NotImplementedException();
|
||||
|
||||
/* public Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}*/
|
||||
|
||||
/* public Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}*/
|
||||
/// <inheritdoc/>
|
||||
public void ExitRemoteEnv()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<FlowEnvInfo> GetEnvInfoAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<SereinProjectData> GetProjectInfoAsync()
|
||||
/// <inheritdoc/>
|
||||
public SereinProjectData GetProjectInfoAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void LoadLibrary(string dllPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool LoadNativeLibraryOfRuning(string file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void LoadProject(string filePath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task LoadProjetAsync(string filePath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SaveProject()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetUIContextOperation(UIContextOperation uiContextOperation)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task StartRemoteServerAsync(int port = 7525)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void StopRemoteServer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo mdInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryUnloadLibrary(string assemblyFullName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 每个节点有独自的MethodDetails实例
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Method)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Method)]
|
||||
public partial class MethodDetails
|
||||
{
|
||||
// private readonly IFlowEnvironment env;
|
||||
@@ -20,57 +20,51 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 对应的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private IFlowNode _nodeModel;
|
||||
|
||||
/// <summary>
|
||||
/// 对应的程序集
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _assemblyName;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 调用节点方法时需要的实例(多个相同的节点将拥有相同的类型)
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private Type _actingInstanceType;
|
||||
|
||||
/// <summary>
|
||||
/// 作用实例(多个相同的节点将会共享同一个实例)
|
||||
/// </summary>
|
||||
// [PropertyInfo]
|
||||
// private object _actingInstance;
|
||||
|
||||
/// <summary>
|
||||
/// 方法名称
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _methodName;
|
||||
|
||||
/// <summary>
|
||||
/// 节点类型
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private NodeType _methodDynamicType;
|
||||
|
||||
/// <summary>
|
||||
/// 锁名称(暂未实现)
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _methodLockName;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 方法别名
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _methodAnotherName;
|
||||
|
||||
/// <summary>
|
||||
/// 参数描述
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private ParameterDetails[] _parameterDetailss;
|
||||
|
||||
/// <summary>
|
||||
@@ -78,19 +72,19 @@ namespace Serein.Library
|
||||
/// <para>-1表示不存在</para>
|
||||
/// <para>0表示第一个参数是可选参数</para>
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private int _paramsArgIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为异步方法(如果为异步方法,则返回值类型为Task或Task<T>)
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private bool _isAsync = false;
|
||||
|
||||
/// <summary>
|
||||
/// 出参类型
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private Type _returnType;
|
||||
}
|
||||
|
||||
@@ -133,7 +127,11 @@ namespace Serein.Library
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 新增可变参数
|
||||
/// </summary>
|
||||
/// <param name="parameterDetails"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddParamsArg(ParameterDetails parameterDetails)
|
||||
{
|
||||
if (ParamsArgIndex < 0) // 方法是否包含可变参数
|
||||
@@ -313,6 +311,10 @@ namespace Serein.Library
|
||||
return md;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将方法信息转换为字符串,方便调试和查看
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.MethodName))
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 节点调试设置,用于中断节点的运行
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.DebugSetting)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.DebugSetting)]
|
||||
public partial class NodeDebugSetting
|
||||
{
|
||||
/// <summary>
|
||||
@@ -24,25 +24,25 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 是否保护参数
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isProtectionParameter = false;
|
||||
|
||||
/// <summary>
|
||||
/// 对应的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private IFlowNode _nodeModel;
|
||||
|
||||
/// <summary>
|
||||
/// 是否使能
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isEnable = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否中断节点。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isInterrupt = false;
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public Type ViewModelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 节点类型信息字符串表示
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"$[{NodeType}]类型信息 : ModelType->{ModelType};ControlType->{ControlType};ViewModelType->{ViewModelType}";
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 节点入参参数详情
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Parameter)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Parameter)]
|
||||
public partial class ParameterDetails
|
||||
{
|
||||
// private readonly IFlowEnvironment env;
|
||||
@@ -22,13 +22,13 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 所在的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private IFlowNode _nodeModel;
|
||||
|
||||
/// <summary>
|
||||
/// 参数索引
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private int _index;
|
||||
|
||||
/// <summary>
|
||||
@@ -36,7 +36,7 @@ namespace Serein.Library
|
||||
/// <para>如果为 true ,则使用输入的文本值作为入参数据。</para>
|
||||
/// <para>如果为 false ,则在当前流程上下文中,根据 ArgDataSourceNodeGuid 查找到对应节点,并根据 ArgDataSourceNodeGuid 判断如何获取其返回的数据,以此作为入参数据。</para>
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true, IsVerify = true)]
|
||||
[DataInfo(IsNotification = true, IsVerify = true)]
|
||||
private bool _isExplicitData ;
|
||||
|
||||
///// <summary>
|
||||
@@ -49,7 +49,7 @@ namespace Serein.Library
|
||||
/// 方法入参若无相关转换器特性标注,则无需关注该变量。该变量用于需要用到枚举BinValue转换器时,指示相应的入参变量需要转为的类型。
|
||||
/// </summary>
|
||||
[Obsolete("转换器特性将在下一个大版本中移除")]
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private Type _explicitType ;
|
||||
|
||||
/// <summary>
|
||||
@@ -58,56 +58,56 @@ namespace Serein.Library
|
||||
/// <para>Bool : 布尔类型</para>
|
||||
/// <para>Value :除以上类型之外的任意参数</para>
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private ParameterValueInputType _inputType ;
|
||||
|
||||
/// <summary>
|
||||
/// 入参数据来源。默认使用上一节点作为入参数据。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private ConnectionArgSourceType _argDataSourceType = ConnectionArgSourceType.GetPreviousNodeData;
|
||||
|
||||
/// <summary>
|
||||
/// 当 ArgDataSourceType 不为 GetPreviousNodeData 时(从运行时上一节点获取数据)。
|
||||
/// 则通过当前上下文,获取该Guid对应的数据作为预处理的入参参数。
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _argDataSourceNodeGuid;
|
||||
|
||||
/// <summary>
|
||||
/// 方法入参需要的类型。
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private Type _dataType ;
|
||||
|
||||
/// <summary>
|
||||
/// 方法入参参数名称
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _name ;
|
||||
|
||||
/// <summary>
|
||||
/// 入参注释
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _description;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义的方法入参数据
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)] // IsPrint = true
|
||||
[DataInfo(IsNotification = true)] // IsPrint = true
|
||||
private string _dataValue;
|
||||
|
||||
/// <summary>
|
||||
/// 只有当 InputType 为 Select 时,才会需要该成员。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string[] _items ;
|
||||
|
||||
/// <summary>
|
||||
/// 指示该属性是可变参数的其中一员(可变参数为数组类型)
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private bool _isParams;
|
||||
}
|
||||
|
||||
@@ -134,6 +134,11 @@ namespace Serein.Library
|
||||
this.NodeModel = nodeModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过参数数据加载实体,用于加载项目文件、远程连接的场景
|
||||
/// </summary>
|
||||
/// <param name="pdInfo"></param>
|
||||
/// <param name="argIndex"></param>
|
||||
public ParameterDetails(ParameterData pdInfo, int argIndex)
|
||||
{
|
||||
this.Index = argIndex;
|
||||
@@ -163,6 +168,7 @@ namespace Serein.Library
|
||||
IsParams = info.IsParams;
|
||||
}
|
||||
|
||||
|
||||
partial void BeforeTheIsExplicitData(ref bool __isAllow, bool newValue)
|
||||
{
|
||||
if(DataType == typeof(IFlowContext))
|
||||
@@ -214,6 +220,12 @@ namespace Serein.Library
|
||||
return pd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转为方法入参数据
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<object> ToMethodArgData(IFlowContext context)
|
||||
{
|
||||
// 1. 从缓存获取
|
||||
@@ -310,177 +322,181 @@ namespace Serein.Library
|
||||
|
||||
|
||||
|
||||
/* /// <summary>
|
||||
/// 转为方法入参数据
|
||||
/* /// <summary>
|
||||
/// 转为方法入参数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<object> ToMethodArgData2(IFlowContext context)
|
||||
{
|
||||
|
||||
var nodeModel = NodeModel;
|
||||
var env = nodeModel.Env;
|
||||
|
||||
#region 流程运行上下文预设的参数
|
||||
if (context.TryGetParamsTempData(NodeModel.Guid, Index, out var data))
|
||||
{
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 显然的流程基本类型
|
||||
// 返回运行环境
|
||||
if (typeof(IFlowEnvironment).IsAssignableFrom(DataType))
|
||||
{
|
||||
return env;
|
||||
}
|
||||
// 返回流程上下文
|
||||
if (typeof(IFlowContext).IsAssignableFrom(DataType))
|
||||
{
|
||||
return context;
|
||||
}
|
||||
// 返回流程上下文
|
||||
if (typeof(IFlowNode).IsAssignableFrom(DataType))
|
||||
{
|
||||
return NodeModel;
|
||||
}
|
||||
// 显式设置的参数
|
||||
if (IsExplicitData && !DataValue.StartsWith("@", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return DataValue.ToConvertValueType(DataType); // 并非表达式,同时是显式设置的参数
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*//*#region “枚举-类型”转换器
|
||||
if (ExplicitType is not null && ExplicitType.IsEnum && DataType != ExplicitType)
|
||||
{
|
||||
var resultEnum = Enum.Parse(ExplicitType, DataValue);
|
||||
// 获取绑定的类型
|
||||
var type = EnumHelper.GetBoundValue(ExplicitType, resultEnum, attr => attr.Value);
|
||||
if (type is Type enumBindType && !(enumBindType is null))
|
||||
{
|
||||
var value = nodeModel.Env.IOC.CreateObject(enumBindType);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
#endregion*//*
|
||||
|
||||
// 需要获取预入参数据
|
||||
object inputParameter;
|
||||
#region (默认的)从运行时上游节点获取其返回值
|
||||
|
||||
if (ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
|
||||
{
|
||||
var previousNode = context.GetPreviousNode(nodeModel.Guid);
|
||||
if (previousNode is null)
|
||||
{
|
||||
inputParameter = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var flowData = context.GetFlowData(previousNode);
|
||||
inputParameter = flowData.Value; // 当前传递的数据
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
if(!env.TryGetNodeModel(ArgDataSourceNodeGuid, out var argSourceNodeModel))
|
||||
{
|
||||
throw new Exception($"[arg{Index}][{Name}][{DataType}]需要节点[{ArgDataSourceNodeGuid}]的参数,但节点不存在");
|
||||
}
|
||||
|
||||
// 如果是公开的节点,需要判断上下文调用中是否存在流程接口节点
|
||||
if (argSourceNodeModel.IsPublic)
|
||||
{
|
||||
var pnGuid = context.GetPreviousNode(NodeModel.Guid);
|
||||
var pn = env.TryGetNodeModel(pnGuid, out var tmpNode) ? tmpNode : null;
|
||||
if (pn.ControlType == NodeControlType.FlowCall)
|
||||
{
|
||||
argSourceNodeModel = pn;
|
||||
}
|
||||
}
|
||||
|
||||
if (ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
|
||||
{
|
||||
var flowData = context.GetFlowData(argSourceNodeModel.Guid);
|
||||
if(flowData is null)
|
||||
{
|
||||
inputParameter = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
inputParameter = flowData.Value;
|
||||
}
|
||||
}
|
||||
else if (ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
|
||||
{
|
||||
// 立刻调用对应节点获取数据。
|
||||
var cts = new CancellationTokenSource();
|
||||
var result = await argSourceNodeModel.ExecutingAsync(context, cts.Token);
|
||||
cts?.Cancel();
|
||||
cts?.Dispose();
|
||||
inputParameter = result.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("节点执行方法获取入参参数时,ConnectionArgSourceType枚举是意外的枚举值");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region 判断是否执行表达式
|
||||
if (IsExplicitData)
|
||||
{
|
||||
// @Get 表达式 (从上一节点获取对象)
|
||||
if (DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inputParameter = SerinExpressionEvaluator.Evaluate(DataValue, inputParameter, out _);
|
||||
}
|
||||
|
||||
// @DTC 表达式 (Data type conversion)
|
||||
else if (DataValue.StartsWith("@dtc", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inputParameter = SerinExpressionEvaluator.Evaluate(DataValue, inputParameter, out _);
|
||||
}
|
||||
|
||||
// @Data 表达式 (获取全局数据)
|
||||
else if (DataValue.StartsWith("@data", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inputParameter = SerinExpressionEvaluator.Evaluate(DataValue, inputParameter, out _);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// 对引用类型检查 null
|
||||
if (!DataType.IsValueType && inputParameter is null)
|
||||
{
|
||||
throw new Exception($"[arg{Index}][{Name}][{DataType}]参数不能为null");
|
||||
}
|
||||
if (DataType == typeof(string)) // 转为字符串
|
||||
{
|
||||
return inputParameter.ToString();
|
||||
}
|
||||
var inputParameterType = inputParameter.GetType();
|
||||
if (DataType.IsSubclassOf(inputParameterType)) // 入参类型 是 预入参数据类型 的 子类/实现类
|
||||
{
|
||||
// 方法入参中,父类不能隐式转为子类,这里需要进行强制转换
|
||||
return ObjectConvertHelper.ConvertParentToChild(inputParameter, DataType);
|
||||
}
|
||||
if (DataType.IsAssignableFrom(inputParameterType)) // 入参类型 是 预入参数据类型 的 父类/接口
|
||||
{
|
||||
return inputParameter;
|
||||
}
|
||||
|
||||
throw new Exception($"[arg{Index}][{Name}][{DataType}]入参类型不符合,当前预入参类型为{inputParameterType}");
|
||||
}
|
||||
*/
|
||||
/// <summary>
|
||||
/// 转为字符串描述
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<object> ToMethodArgData2(IFlowContext context)
|
||||
{
|
||||
|
||||
var nodeModel = NodeModel;
|
||||
var env = nodeModel.Env;
|
||||
|
||||
#region 流程运行上下文预设的参数
|
||||
if (context.TryGetParamsTempData(NodeModel.Guid, Index, out var data))
|
||||
{
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 显然的流程基本类型
|
||||
// 返回运行环境
|
||||
if (typeof(IFlowEnvironment).IsAssignableFrom(DataType))
|
||||
{
|
||||
return env;
|
||||
}
|
||||
// 返回流程上下文
|
||||
if (typeof(IFlowContext).IsAssignableFrom(DataType))
|
||||
{
|
||||
return context;
|
||||
}
|
||||
// 返回流程上下文
|
||||
if (typeof(IFlowNode).IsAssignableFrom(DataType))
|
||||
{
|
||||
return NodeModel;
|
||||
}
|
||||
// 显式设置的参数
|
||||
if (IsExplicitData && !DataValue.StartsWith("@", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return DataValue.ToConvertValueType(DataType); // 并非表达式,同时是显式设置的参数
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*//*#region “枚举-类型”转换器
|
||||
if (ExplicitType is not null && ExplicitType.IsEnum && DataType != ExplicitType)
|
||||
{
|
||||
var resultEnum = Enum.Parse(ExplicitType, DataValue);
|
||||
// 获取绑定的类型
|
||||
var type = EnumHelper.GetBoundValue(ExplicitType, resultEnum, attr => attr.Value);
|
||||
if (type is Type enumBindType && !(enumBindType is null))
|
||||
{
|
||||
var value = nodeModel.Env.IOC.CreateObject(enumBindType);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
#endregion*//*
|
||||
|
||||
// 需要获取预入参数据
|
||||
object inputParameter;
|
||||
#region (默认的)从运行时上游节点获取其返回值
|
||||
|
||||
if (ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
|
||||
{
|
||||
var previousNode = context.GetPreviousNode(nodeModel.Guid);
|
||||
if (previousNode is null)
|
||||
{
|
||||
inputParameter = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var flowData = context.GetFlowData(previousNode);
|
||||
inputParameter = flowData.Value; // 当前传递的数据
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
if(!env.TryGetNodeModel(ArgDataSourceNodeGuid, out var argSourceNodeModel))
|
||||
{
|
||||
throw new Exception($"[arg{Index}][{Name}][{DataType}]需要节点[{ArgDataSourceNodeGuid}]的参数,但节点不存在");
|
||||
}
|
||||
|
||||
// 如果是公开的节点,需要判断上下文调用中是否存在流程接口节点
|
||||
if (argSourceNodeModel.IsPublic)
|
||||
{
|
||||
var pnGuid = context.GetPreviousNode(NodeModel.Guid);
|
||||
var pn = env.TryGetNodeModel(pnGuid, out var tmpNode) ? tmpNode : null;
|
||||
if (pn.ControlType == NodeControlType.FlowCall)
|
||||
{
|
||||
argSourceNodeModel = pn;
|
||||
}
|
||||
}
|
||||
|
||||
if (ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
|
||||
{
|
||||
var flowData = context.GetFlowData(argSourceNodeModel.Guid);
|
||||
if(flowData is null)
|
||||
{
|
||||
inputParameter = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
inputParameter = flowData.Value;
|
||||
}
|
||||
}
|
||||
else if (ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
|
||||
{
|
||||
// 立刻调用对应节点获取数据。
|
||||
var cts = new CancellationTokenSource();
|
||||
var result = await argSourceNodeModel.ExecutingAsync(context, cts.Token);
|
||||
cts?.Cancel();
|
||||
cts?.Dispose();
|
||||
inputParameter = result.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("节点执行方法获取入参参数时,ConnectionArgSourceType枚举是意外的枚举值");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region 判断是否执行表达式
|
||||
if (IsExplicitData)
|
||||
{
|
||||
// @Get 表达式 (从上一节点获取对象)
|
||||
if (DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inputParameter = SerinExpressionEvaluator.Evaluate(DataValue, inputParameter, out _);
|
||||
}
|
||||
|
||||
// @DTC 表达式 (Data type conversion)
|
||||
else if (DataValue.StartsWith("@dtc", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inputParameter = SerinExpressionEvaluator.Evaluate(DataValue, inputParameter, out _);
|
||||
}
|
||||
|
||||
// @Data 表达式 (获取全局数据)
|
||||
else if (DataValue.StartsWith("@data", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inputParameter = SerinExpressionEvaluator.Evaluate(DataValue, inputParameter, out _);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// 对引用类型检查 null
|
||||
if (!DataType.IsValueType && inputParameter is null)
|
||||
{
|
||||
throw new Exception($"[arg{Index}][{Name}][{DataType}]参数不能为null");
|
||||
}
|
||||
if (DataType == typeof(string)) // 转为字符串
|
||||
{
|
||||
return inputParameter.ToString();
|
||||
}
|
||||
var inputParameterType = inputParameter.GetType();
|
||||
if (DataType.IsSubclassOf(inputParameterType)) // 入参类型 是 预入参数据类型 的 子类/实现类
|
||||
{
|
||||
// 方法入参中,父类不能隐式转为子类,这里需要进行强制转换
|
||||
return ObjectConvertHelper.ConvertParentToChild(inputParameter, DataType);
|
||||
}
|
||||
if (DataType.IsAssignableFrom(inputParameterType)) // 入参类型 是 预入参数据类型 的 父类/接口
|
||||
{
|
||||
return inputParameter;
|
||||
}
|
||||
|
||||
throw new Exception($"[arg{Index}][{Name}][{DataType}]入参类型不符合,当前预入参类型为{inputParameterType}");
|
||||
}
|
||||
*/
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{this.Index}] {(string.IsNullOrWhiteSpace(this.Description) ? string.Empty : $"({this.Description})")}{this.Name} : {this.DataType?.FullName}";
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 节点于画布中的位置(通用类)
|
||||
/// </summary>
|
||||
[NodeProperty]
|
||||
[FlowDataProperty]
|
||||
public partial class PositionOfUI
|
||||
{
|
||||
/// <summary>
|
||||
@@ -285,13 +285,13 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 指示控件在画布的横向向方向上的位置
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private double _x = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 指示控件在画布的纵向方向上的位置
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private double _y = 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user