2024-10-20 12:10:57 +08:00
|
|
|
|
using Serein.Library.Api;
|
2024-10-27 00:54:10 +08:00
|
|
|
|
using Serein.Library.Utils;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
using System;
|
2025-07-29 14:51:14 +08:00
|
|
|
|
using System.ComponentModel.DataAnnotations;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
using System.Linq;
|
2024-12-26 16:42:05 +08:00
|
|
|
|
using System.Reflection;
|
2025-03-21 18:26:01 +08:00
|
|
|
|
using System.Threading;
|
2024-12-26 16:42:05 +08:00
|
|
|
|
using System.Threading.Tasks;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
namespace Serein.Library
|
|
|
|
|
|
{
|
|
|
|
|
|
|
2025-03-15 15:43:42 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 节点入参参数详情
|
|
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[FlowDataProperty(ValuePath = NodeValuePath.Parameter)]
|
2024-10-20 12:10:57 +08:00
|
|
|
|
public partial class ParameterDetails
|
|
|
|
|
|
{
|
2024-11-02 16:48:40 +08:00
|
|
|
|
// private readonly IFlowEnvironment env;
|
2024-10-23 19:22:27 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-10-24 23:32:43 +08:00
|
|
|
|
/// 所在的节点
|
2024-10-23 19:22:27 +08:00
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo(IsProtection = true)]
|
2025-05-31 12:15:01 +08:00
|
|
|
|
private IFlowNode _nodeModel;
|
2024-10-23 19:22:27 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 参数索引
|
|
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo]
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private int _index;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-10-24 23:32:43 +08:00
|
|
|
|
/// <para>是否为显式参数(固定值/表达式)</para>
|
2025-07-26 19:36:54 +08:00
|
|
|
|
/// <para>如果为 true ,则使用输入的文本值作为入参数据。</para>
|
2025-07-18 23:34:08 +08:00
|
|
|
|
/// <para>如果为 false ,则在当前流程上下文中,根据 ArgDataSourceNodeGuid 查找到对应节点,并根据 ArgDataSourceNodeGuid 判断如何获取其返回的数据,以此作为入参数据。</para>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo(IsNotification = true, IsVerify = true)]
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private bool _isExplicitData ;
|
|
|
|
|
|
|
2024-12-14 23:46:37 +08:00
|
|
|
|
///// <summary>
|
|
|
|
|
|
///// 转换器 IEnumConvertor<,>
|
|
|
|
|
|
///// </summary>
|
|
|
|
|
|
//[PropertyInfo]
|
|
|
|
|
|
//private Func<object, object> _convertor ;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-10-24 23:32:43 +08:00
|
|
|
|
/// 方法入参若无相关转换器特性标注,则无需关注该变量。该变量用于需要用到枚举BinValue转换器时,指示相应的入参变量需要转为的类型。
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// </summary>
|
2025-07-18 23:34:08 +08:00
|
|
|
|
[Obsolete("转换器特性将在下一个大版本中移除")]
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo]
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private Type _explicitType ;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 目前存在三种状态:Select/Bool/Value
|
2024-11-02 16:48:40 +08:00
|
|
|
|
/// <para>Select : 枚举值/可选值</para>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <para>Bool : 布尔类型</para>
|
2024-11-02 16:48:40 +08:00
|
|
|
|
/// <para>Value :除以上类型之外的任意参数</para>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo]
|
2025-03-15 15:43:42 +08:00
|
|
|
|
private ParameterValueInputType _inputType ;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-10-24 23:32:43 +08:00
|
|
|
|
/// 入参数据来源。默认使用上一节点作为入参数据。
|
|
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo(IsNotification = true)]
|
2024-10-24 23:32:43 +08:00
|
|
|
|
private ConnectionArgSourceType _argDataSourceType = ConnectionArgSourceType.GetPreviousNodeData;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当 ArgDataSourceType 不为 GetPreviousNodeData 时(从运行时上一节点获取数据)。
|
2024-10-27 00:54:10 +08:00
|
|
|
|
/// 则通过当前上下文,获取该Guid对应的数据作为预处理的入参参数。
|
2024-10-24 23:32:43 +08:00
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo]
|
2024-10-27 00:54:10 +08:00
|
|
|
|
private string _argDataSourceNodeGuid;
|
2024-10-24 23:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 方法入参需要的类型。
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo]
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private Type _dataType ;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 方法入参参数名称
|
|
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo(IsNotification = true)]
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private string _name ;
|
|
|
|
|
|
|
2025-03-15 16:03:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 入参注释
|
|
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo]
|
2025-03-15 16:03:58 +08:00
|
|
|
|
private string _description;
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 自定义的方法入参数据
|
|
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo(IsNotification = true)] // IsPrint = true
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private string _dataValue;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-03-15 15:43:42 +08:00
|
|
|
|
/// 只有当 InputType 为 Select 时,才会需要该成员。
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo(IsNotification = true)]
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private string[] _items ;
|
2024-11-02 16:48:40 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 指示该属性是可变参数的其中一员(可变参数为数组类型)
|
|
|
|
|
|
/// </summary>
|
2025-07-30 21:15:07 +08:00
|
|
|
|
[DataInfo]
|
2024-11-02 16:48:40 +08:00
|
|
|
|
private bool _isParams;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-03-15 15:43:42 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
public partial class ParameterDetails
|
|
|
|
|
|
{
|
2025-06-01 12:21:38 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 用于创建元数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public ParameterDetails()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 为节点实例化新的入参描述
|
|
|
|
|
|
/// </summary>
|
2025-05-31 12:15:01 +08:00
|
|
|
|
public ParameterDetails(IFlowNode nodeModel)
|
2024-10-20 12:10:57 +08:00
|
|
|
|
{
|
2024-10-23 19:22:27 +08:00
|
|
|
|
this.NodeModel = nodeModel;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
}
|
2024-10-24 23:32:43 +08:00
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 通过参数数据加载实体,用于加载项目文件、远程连接的场景
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="pdInfo"></param>
|
|
|
|
|
|
/// <param name="argIndex"></param>
|
2025-05-30 15:42:59 +08:00
|
|
|
|
public ParameterDetails(ParameterData pdInfo, int argIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.Index = argIndex;
|
|
|
|
|
|
this.DataType = typeof(object);
|
|
|
|
|
|
this.ArgDataSourceNodeGuid = pdInfo.SourceNodeGuid;
|
|
|
|
|
|
this.ArgDataSourceType = EnumHelper.ConvertEnum<ConnectionArgSourceType>(pdInfo.SourceType);
|
|
|
|
|
|
this.DataValue = pdInfo.Value;
|
|
|
|
|
|
this.InputType = ParameterValueInputType.Input;
|
|
|
|
|
|
this.IsExplicitData = pdInfo.State;
|
|
|
|
|
|
this.Name = pdInfo.ArgName;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-29 14:51:14 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 通过参数信息加载实体,用于加载项目文件、远程连接的场景
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="info">参数信息</param>
|
|
|
|
|
|
public ParameterDetails(ParameterDetailsInfo info)
|
|
|
|
|
|
{
|
|
|
|
|
|
Index = info.Index;
|
|
|
|
|
|
Name = info.Name;
|
|
|
|
|
|
DataType = Type.GetType(info.DataTypeFullName);
|
|
|
|
|
|
ExplicitType = Type.GetType(info.ExplicitTypeFullName);
|
2025-03-15 15:43:42 +08:00
|
|
|
|
InputType = info.InputType.ConvertEnum<ParameterValueInputType>();
|
2024-10-20 12:10:57 +08:00
|
|
|
|
Items = info.Items;
|
2025-07-29 18:36:43 +08:00
|
|
|
|
IsParams = info.IsParams;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
|
2025-07-29 18:36:43 +08:00
|
|
|
|
partial void BeforeTheIsExplicitData(ref bool __isAllow, bool newValue)
|
2025-07-29 14:51:14 +08:00
|
|
|
|
{
|
|
|
|
|
|
if(DataType == typeof(IFlowContext))
|
|
|
|
|
|
{
|
2025-07-29 18:36:43 +08:00
|
|
|
|
__isAllow = false;
|
2025-07-29 14:51:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-29 18:36:43 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 转为描述
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public ParameterDetailsInfo ToInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
return new ParameterDetailsInfo
|
|
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
Index = this.Index,
|
2024-11-02 22:11:38 +08:00
|
|
|
|
IsParams = this.IsParams,
|
2024-10-27 00:54:10 +08:00
|
|
|
|
DataTypeFullName = this.DataType.FullName,
|
|
|
|
|
|
Name = this.Name,
|
2025-05-30 23:31:31 +08:00
|
|
|
|
ExplicitTypeFullName = this.ExplicitType?.FullName,
|
2025-03-15 15:43:42 +08:00
|
|
|
|
InputType = this.InputType.ToString(),
|
2025-05-30 23:31:31 +08:00
|
|
|
|
Items = this.Items?.Select(it => it).ToArray(),
|
2024-10-20 12:10:57 +08:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-11-02 16:48:40 +08:00
|
|
|
|
/// 为某个节点从元数据中拷贝方法描述的入参描述
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// </summary>
|
2024-10-27 00:54:10 +08:00
|
|
|
|
/// <param name="nodeModel">对应的节点</param>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <returns></returns>
|
2025-05-31 12:15:01 +08:00
|
|
|
|
public ParameterDetails CloneOfModel(IFlowNode nodeModel)
|
2024-10-20 12:10:57 +08:00
|
|
|
|
{
|
2024-11-02 16:48:40 +08:00
|
|
|
|
var pd = new ParameterDetails(nodeModel)
|
2024-10-20 12:10:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
Index = this.Index,
|
|
|
|
|
|
IsExplicitData = this.IsExplicitData,
|
|
|
|
|
|
ExplicitType = this.ExplicitType,
|
2025-03-15 15:43:42 +08:00
|
|
|
|
InputType = this.InputType,
|
2024-12-14 23:46:37 +08:00
|
|
|
|
//Convertor = this.Convertor,
|
2024-10-20 12:10:57 +08:00
|
|
|
|
DataType = this.DataType,
|
|
|
|
|
|
Name = this.Name,
|
2025-05-28 23:19:00 +08:00
|
|
|
|
DataValue = this.DataValue,
|
2024-10-20 12:10:57 +08:00
|
|
|
|
Items = this.Items?.Select(it => it).ToArray(),
|
2024-11-02 22:11:38 +08:00
|
|
|
|
IsParams = this.IsParams,
|
2025-03-15 16:03:58 +08:00
|
|
|
|
Description = this.Description,
|
2024-10-20 12:10:57 +08:00
|
|
|
|
};
|
|
|
|
|
|
return pd;
|
|
|
|
|
|
}
|
2024-10-28 15:21:08 +08:00
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 转为方法入参数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="context"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
/// <exception cref="Exception"></exception>
|
2025-07-23 16:20:41 +08:00
|
|
|
|
public async Task<object> ToMethodArgData(IFlowContext context)
|
2025-07-06 14:34:49 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 1. 从缓存获取
|
|
|
|
|
|
if (context.TryGetParamsTempData(NodeModel.Guid, Index, out var data))
|
|
|
|
|
|
return data;
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 特定快捷类型
|
2025-07-23 16:20:41 +08:00
|
|
|
|
if (typeof(IFlowContext).IsAssignableFrom(DataType)) return context;
|
2025-07-29 14:51:14 +08:00
|
|
|
|
//if (typeof(IFlowEnvironment).IsAssignableFrom(DataType)) return NodeModel.Env;
|
|
|
|
|
|
//if (typeof(IFlowNode).IsAssignableFrom(DataType)) return NodeModel;
|
2025-07-06 14:34:49 +08:00
|
|
|
|
|
|
|
|
|
|
// 3. 显式常量参数
|
|
|
|
|
|
if (IsExplicitData && !DataValue.StartsWith("@", StringComparison.OrdinalIgnoreCase))
|
2025-07-27 23:34:01 +08:00
|
|
|
|
return DataValue.ToConvertValueType(DataType);
|
2025-07-06 14:34:49 +08:00
|
|
|
|
|
2025-07-26 19:36:54 +08:00
|
|
|
|
// 4. 来自其他节点
|
2025-07-06 14:34:49 +08:00
|
|
|
|
object inputParameter = null;
|
|
|
|
|
|
var env = NodeModel.Env;
|
|
|
|
|
|
|
|
|
|
|
|
if (ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
|
|
|
|
|
|
{
|
2025-07-26 19:36:54 +08:00
|
|
|
|
var prevNodeGuid = context.GetPreviousNode(NodeModel.Guid);
|
2025-07-29 14:51:14 +08:00
|
|
|
|
if(prevNodeGuid is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
inputParameter = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var prevNodeData = context.GetFlowData(prevNodeGuid);
|
|
|
|
|
|
inputParameter = prevNodeData.Value;
|
|
|
|
|
|
}
|
2025-07-06 14:34:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
var prevNodeGuid = context.GetPreviousNode(NodeModel.Guid);
|
|
|
|
|
|
|
|
|
|
|
|
if (!env.TryGetNodeModel(ArgDataSourceNodeGuid, out var sourceNode))
|
|
|
|
|
|
throw new Exception($"[arg{Index}] 节点[{ArgDataSourceNodeGuid}]不存在");
|
|
|
|
|
|
|
2025-07-26 19:36:54 +08:00
|
|
|
|
if (sourceNode.IsPublic // 如果运行上一节点是[FlowCall]节点(则从该节点获取入参)
|
2025-07-06 14:34:49 +08:00
|
|
|
|
&& env.TryGetNodeModel(prevNodeGuid, out var prevNode)
|
|
|
|
|
|
&& prevNode.ControlType == NodeControlType.FlowCall
|
|
|
|
|
|
&& env.TryGetNodeModel(context.GetPreviousNode(NodeModel.Guid), out var sourceNodeTemp)
|
|
|
|
|
|
)
|
|
|
|
|
|
sourceNode = sourceNodeTemp;
|
|
|
|
|
|
|
|
|
|
|
|
if (ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
|
2025-07-28 17:38:51 +08:00
|
|
|
|
{
|
|
|
|
|
|
|
2025-07-06 14:34:49 +08:00
|
|
|
|
inputParameter = context.GetFlowData(sourceNode.Guid)?.Value;
|
2025-07-28 17:38:51 +08:00
|
|
|
|
}
|
2025-07-26 19:36:54 +08:00
|
|
|
|
else if (ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke) // 立刻执行目标节点获取参数
|
2025-07-28 17:38:51 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (context.IsRecordInvokeInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
var invokeInfo = context.NewInvokeInfo(NodeModel, sourceNode, FlowInvokeInfo.InvokeType.ArgSource);
|
|
|
|
|
|
var result = await sourceNode.ExecutingAsync(context, CancellationToken.None);
|
|
|
|
|
|
inputParameter = result.Value;
|
|
|
|
|
|
invokeInfo.UploadResultValue(result.Value);
|
|
|
|
|
|
invokeInfo.UploadState(FlowInvokeInfo.RunState.Succeed);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = await sourceNode.ExecutingAsync(context, CancellationToken.None);
|
|
|
|
|
|
inputParameter = result.Value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-06 14:34:49 +08:00
|
|
|
|
else
|
2025-07-28 17:38:51 +08:00
|
|
|
|
{
|
|
|
|
|
|
|
2025-07-06 14:34:49 +08:00
|
|
|
|
throw new Exception("无效的 ArgDataSourceType");
|
2025-07-28 17:38:51 +08:00
|
|
|
|
}
|
2025-07-06 14:34:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-28 20:04:56 +08:00
|
|
|
|
// 5. 类型转换
|
2025-07-06 14:34:49 +08:00
|
|
|
|
if (!DataType.IsValueType && inputParameter is null)
|
|
|
|
|
|
throw new Exception($"[arg{Index}] 参数不能为null");
|
|
|
|
|
|
|
|
|
|
|
|
if (DataType == typeof(string))
|
|
|
|
|
|
return inputParameter.ToString();
|
|
|
|
|
|
|
|
|
|
|
|
var actualType = inputParameter.GetType();
|
|
|
|
|
|
if (DataType.IsAssignableFrom(actualType))
|
|
|
|
|
|
return inputParameter;
|
|
|
|
|
|
|
|
|
|
|
|
if (DataType.IsSubclassOf(actualType))
|
|
|
|
|
|
return ObjectConvertHelper.ConvertParentToChild(inputParameter, DataType);
|
|
|
|
|
|
|
|
|
|
|
|
throw new Exception($"[arg{Index}] 类型不匹配:目标类型为 {DataType},实际类型为 {actualType}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-28 20:04:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/* /// <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>
|
|
|
|
|
|
/// 转为字符串描述
|
2024-12-26 16:42:05 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2024-10-28 15:21:08 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
|
{
|
2025-07-31 09:54:30 +08:00
|
|
|
|
return $"[{this.Index}] {(string.IsNullOrWhiteSpace(this.Description) ? string.Empty : $"({this.Description})")}{this.Name} : {this.DataType?.GetFriendlyName()}";
|
2024-10-28 15:21:08 +08:00
|
|
|
|
}
|
2024-10-20 12:10:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|