2024-08-06 16:09:46 +08:00
using Newtonsoft.Json ;
2024-09-18 16:45:41 +08:00
using Newtonsoft.Json.Linq ;
2024-09-12 20:32:54 +08:00
using Serein.Library.Api ;
2024-09-27 10:30:19 +08:00
using Serein.Library.Attributes ;
2024-09-15 12:15:32 +08:00
using Serein.Library.Entity ;
2024-09-12 20:32:54 +08:00
using Serein.Library.Enums ;
2024-09-15 22:07:10 +08:00
using Serein.Library.Ex ;
2024-09-27 10:30:19 +08:00
using Serein.Library.Utils ;
2024-10-07 22:52:10 +08:00
using Serein.NodeFlow.Tool ;
2024-09-16 19:53:36 +08:00
using Serein.NodeFlow.Tool.SereinExpression ;
2024-09-15 12:15:32 +08:00
using System ;
2024-10-07 22:52:10 +08:00
using System.Collections ;
2024-09-15 12:15:32 +08:00
using System.Collections.Generic ;
using System.Linq ;
2024-09-22 14:10:13 +08:00
using System.Linq.Expressions ;
2024-09-18 16:45:41 +08:00
using System.Net.Http.Headers ;
2024-09-27 10:30:19 +08:00
using System.Reflection ;
2024-09-15 12:15:32 +08:00
using System.Text ;
using System.Threading.Tasks ;
2024-09-21 10:06:44 +08:00
using System.Xml.Linq ;
2024-09-20 10:50:32 +08:00
using static Serein . Library . Utils . ChannelFlowInterrupt ;
2024-08-06 16:09:46 +08:00
2024-09-15 12:15:32 +08:00
namespace Serein.NodeFlow.Base
2024-08-06 16:09:46 +08:00
{
/// <summary>
/// 节点基类(数据):条件控件,动作控件,条件区域,动作区域
/// </summary>
2024-09-15 12:15:32 +08:00
public abstract partial class NodeModelBase : IDynamicFlowNode
2024-08-06 16:09:46 +08:00
{
2024-09-20 10:50:32 +08:00
#region 调 试 中 断
2024-09-21 10:06:44 +08:00
2024-09-20 10:50:32 +08:00
/// <summary>
/// 不再中断
/// </summary>
public void CancelInterrupt ( )
{
this . DebugSetting . InterruptClass = InterruptClass . None ;
2024-09-22 17:37:32 +08:00
DebugSetting . CancelInterruptCallback ? . Invoke ( ) ;
2024-09-20 10:50:32 +08:00
}
2024-09-22 17:37:32 +08:00
2024-09-20 10:50:32 +08:00
#endregion
2024-09-18 16:45:41 +08:00
#region 导 出 / 导 入 项 目 文 件 节 点 信 息
2024-09-17 14:20:27 +08:00
internal abstract Parameterdata [ ] GetParameterdatas ( ) ;
internal virtual NodeInfo ToInfo ( )
2024-09-15 12:15:32 +08:00
{
2024-09-17 14:20:27 +08:00
// if (MethodDetails == null) return null;
2024-08-06 16:09:46 +08:00
2024-09-15 12:15:32 +08:00
var trueNodes = SuccessorNodes [ ConnectionType . IsSucceed ] . Select ( item = > item . Guid ) ; // 真分支
var falseNodes = SuccessorNodes [ ConnectionType . IsFail ] . Select ( item = > item . Guid ) ; // 假分支
2024-09-17 14:20:27 +08:00
var errorNodes = SuccessorNodes [ ConnectionType . IsError ] . Select ( item = > item . Guid ) ; // 异常分支
var upstreamNodes = SuccessorNodes [ ConnectionType . Upstream ] . Select ( item = > item . Guid ) ; // 上游分支
2024-09-09 16:42:01 +08:00
2024-09-15 12:15:32 +08:00
// 生成参数列表
Parameterdata [ ] parameterData = GetParameterdatas ( ) ;
2024-08-06 16:09:46 +08:00
2024-09-15 12:15:32 +08:00
return new NodeInfo
{
Guid = Guid ,
MethodName = MethodDetails ? . MethodName ,
Label = DisplayName ? ? "" ,
Type = this . GetType ( ) . ToString ( ) ,
TrueNodes = trueNodes . ToArray ( ) ,
FalseNodes = falseNodes . ToArray ( ) ,
UpstreamNodes = upstreamNodes . ToArray ( ) ,
ParameterData = parameterData . ToArray ( ) ,
ErrorNodes = errorNodes . ToArray ( ) ,
2024-09-18 16:45:41 +08:00
2024-09-15 12:15:32 +08:00
} ;
}
2024-08-06 16:09:46 +08:00
2024-09-17 14:20:27 +08:00
internal virtual NodeModelBase LoadInfo ( NodeInfo nodeInfo )
{
2024-09-30 22:20:02 +08:00
this . Guid = nodeInfo . Guid ;
if ( this . MethodDetails is not null )
2024-09-17 14:20:27 +08:00
{
for ( int i = 0 ; i < nodeInfo . ParameterData . Length ; i + + )
{
Parameterdata ? pd = nodeInfo . ParameterData [ i ] ;
2024-09-30 22:20:02 +08:00
this . MethodDetails . ExplicitDatas [ i ] . IsExplicitData = pd . State ;
this . MethodDetails . ExplicitDatas [ i ] . DataValue = pd . Value ;
2024-09-17 14:20:27 +08:00
}
}
2024-09-30 22:20:02 +08:00
2024-09-17 14:20:27 +08:00
return this ;
}
2024-09-15 19:48:27 +08:00
2024-09-18 16:45:41 +08:00
#endregion
2024-09-15 19:48:27 +08:00
2024-09-20 10:50:32 +08:00
#region 节 点 方 法 的 执 行
2024-09-15 19:48:27 +08:00
/// <summary>
/// 开始执行
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
2024-09-20 10:50:32 +08:00
public async Task StartExecute ( IDynamicContext context )
2024-09-15 19:48:27 +08:00
{
2024-09-22 14:10:13 +08:00
Stack < NodeModelBase > stack = new Stack < NodeModelBase > ( ) ;
stack . Push ( this ) ;
2024-10-07 22:52:10 +08:00
var flowCts = context . Env . IOC . Get < CancellationTokenSource > ( FlowStarter . FlipFlopCtsName ) ;
2024-09-25 22:20:23 +08:00
while ( stack . Count > 0 ) // 循环中直到栈为空才会退出循环
2024-09-15 19:48:27 +08:00
{
2024-10-07 22:52:10 +08:00
if ( flowCts is not null )
2024-09-25 22:20:23 +08:00
{
2024-10-07 22:52:10 +08:00
if ( flowCts . IsCancellationRequested )
2024-09-25 22:20:23 +08:00
break ;
}
2024-09-22 14:10:13 +08:00
// 从栈中弹出一个节点作为当前节点进行处理
var currentNode = stack . Pop ( ) ;
2024-09-15 19:48:27 +08:00
2024-09-22 14:10:13 +08:00
#region 执 行 相 关
2024-09-20 10:50:32 +08:00
2024-10-07 22:52:10 +08:00
// 筛选出上游分支
var upstreamNodes = currentNode . SuccessorNodes [ ConnectionType . Upstream ] . Where (
node = > node . DebugSetting . IsEnable
) . ToArray ( ) ;
// 执行上游分支
foreach ( var upstreamNode in upstreamNodes )
2024-09-22 14:10:13 +08:00
{
2024-10-07 22:52:10 +08:00
if ( upstreamNode . DebugSetting . IsEnable )
2024-09-21 10:06:44 +08:00
{
2024-10-07 22:52:10 +08:00
if ( upstreamNode . DebugSetting . InterruptClass ! = InterruptClass . None ) // 执行触发前
{
var cancelType = await upstreamNode . DebugSetting . GetInterruptTask ( ) ;
await Console . Out . WriteLineAsync ( $"[{upstreamNode.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支" ) ;
}
upstreamNode . PreviousNode = currentNode ;
await upstreamNode . StartExecute ( context ) ; // 执行流程节点的上游分支
if ( upstreamNode . NextOrientation = = ConnectionType . IsError )
2024-09-22 17:37:32 +08:00
{
2024-10-07 22:52:10 +08:00
// 如果上游分支执行失败,不再继续执行
// 使上游节点(仅上游节点本身,不包含上游节点的后继节点)
// 具备通过抛出异常中断流程的能力
break ;
2024-09-22 17:37:32 +08:00
}
2024-09-20 10:50:32 +08:00
}
2024-09-21 10:06:44 +08:00
}
2024-10-07 22:52:10 +08:00
// 上游分支执行完成,才执行当前节点
2024-09-22 17:37:32 +08:00
object? newFlowData = await currentNode . ExecutingAsync ( context ) ;
2024-10-07 22:52:10 +08:00
if ( flowCts is null | | flowCts . IsCancellationRequested | | currentNode . NextOrientation = = ConnectionType . None )
2024-09-22 14:10:13 +08:00
{
// 不再执行
break ;
}
2024-09-22 17:37:32 +08:00
await RefreshFlowDataAndExpInterrupt ( context , currentNode , newFlowData ) ; // 执行当前节点后刷新数据
#endregion
2024-09-22 14:10:13 +08:00
2024-09-22 17:37:32 +08:00
#region 执 行 完 成
2024-09-22 14:10:13 +08:00
// 选择后继分支
var nextNodes = currentNode . SuccessorNodes [ currentNode . NextOrientation ] ;
// 将下一个节点集合中的所有节点逆序推入栈中
for ( int i = nextNodes . Count - 1 ; i > = 0 ; i - - )
{
2024-10-07 22:52:10 +08:00
// 筛选出启用的节点的节点
if ( nextNodes [ i ] . DebugSetting . IsEnable )
2024-09-22 14:10:13 +08:00
{
nextNodes [ i ] . PreviousNode = currentNode ;
stack . Push ( nextNodes [ i ] ) ;
}
}
#endregion
2024-09-22 17:37:32 +08:00
2024-09-22 14:10:13 +08:00
}
2024-09-20 10:50:32 +08:00
}
2024-09-15 19:48:27 +08:00
2024-10-07 22:52:10 +08:00
2024-09-09 16:42:01 +08:00
/// <summary>
/// 执行节点对应的方法
/// </summary>
/// <param name="context">流程上下文</param>
/// <returns>节点传回数据对象</returns>
2024-09-20 10:50:32 +08:00
public virtual async Task < object? > ExecutingAsync ( IDynamicContext context )
2024-08-06 16:09:46 +08:00
{
2024-09-20 10:50:32 +08:00
#region 调 试 中 断
2024-09-22 17:37:32 +08:00
2024-10-07 22:52:10 +08:00
if ( DebugSetting . InterruptClass ! = InterruptClass . None ) // 执行触发检查是否需要中断
2024-09-20 10:50:32 +08:00
{
2024-10-07 22:52:10 +08:00
var cancelType = await this . DebugSetting . GetInterruptTask ( ) ; // 等待中断结束
2024-09-30 22:20:02 +08:00
await Console . Out . WriteLineAsync ( $"[{this.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支" ) ;
2024-09-20 10:50:32 +08:00
}
#endregion
2024-09-30 22:20:02 +08:00
MethodDetails ? md = MethodDetails ;
2024-09-30 02:45:49 +08:00
//var del = md.MethodDelegate.Clone();
2024-09-30 22:20:02 +08:00
if ( md is null )
{
throw new Exception ( $"节点{this.Guid}不存在方法信息, 请检查是否需要重写节点的ExecutingAsync" ) ;
}
2024-10-10 10:45:53 +08:00
if ( ! context . Env . TryGetDelegateDetails ( md . MethodName , out var dd ) )
2024-09-30 02:45:49 +08:00
{
2024-09-30 22:20:02 +08:00
throw new Exception ( $"节点{this.Guid}不存在对应委托" ) ;
2024-09-30 02:45:49 +08:00
}
2024-09-30 22:20:02 +08:00
md . ActingInstance ? ? = context . Env . IOC . Get ( md . ActingInstanceType ) ;
2024-09-18 16:45:41 +08:00
object instance = md . ActingInstance ;
2024-10-10 10:45:53 +08:00
//bool haveParameter = md.ExplicitDatas.Length > 0;
//bool haveResult = md.ReturnType != typeof(void);
// Type? taskResult = null;
//bool isTask = md.ReturnType is not null && MethodDetailsHelper.IsGenericTask(md.ReturnType, out taskResult);
//bool isTaskHaveResult = taskResult is not null;
object? result = null ;
2024-10-07 22:52:10 +08:00
2024-10-08 11:25:51 +08:00
//Console.WriteLine($"(isTask, isTaskHaveResult):{(isTask, isTaskHaveResult)}");
2024-09-09 16:42:01 +08:00
try
2024-08-06 16:09:46 +08:00
{
2024-09-18 16:45:41 +08:00
// Action/Func([方法作用的实例],[可能的参数值],[可能的返回值])
2024-10-07 22:52:10 +08:00
2024-10-10 10:45:53 +08:00
object? [ ] ? args = GetParameters ( context , this , md ) ;
var delType = dd . EmitMethodType ;
var del = dd . EmitDelegate ;
if ( delType = = EmitHelper . EmitMethodType . HasResultTask & & del is Func < object , object? [ ] ? , Task < object? > > hasResultTask )
2024-10-07 22:52:10 +08:00
{
2024-10-10 10:45:53 +08:00
result = await hasResultTask ( instance , args ) ;
}
else if ( delType = = EmitHelper . EmitMethodType . Task & & del is Func < object , object? [ ] ? , Task > task )
{
await task . Invoke ( instance , args ) ;
result = null ;
}
else if ( delType = = EmitHelper . EmitMethodType . Func & & del is Func < object , object? [ ] ? , object? > func )
{
result = func . Invoke ( instance , args ) ;
2024-10-07 22:52:10 +08:00
}
else
2024-08-06 16:09:46 +08:00
{
2024-10-10 10:45:53 +08:00
throw new NotImplementedException ( "构造委托无法正确调用" ) ;
2024-10-07 22:52:10 +08:00
}
2024-09-21 10:06:44 +08:00
2024-10-10 10:45:53 +08:00
//if (isTask)
//{
// // 异步方法( 因为返回了Task, 所以排除Action<>委托的可能)
// result = (haveParameter, isTaskHaveResult) switch
// {
// (false, false) => await ExecutionAsync((Func<object, Task>)del, instance), // 调用节点方法,返回方法传回类型
// (true, false) => await ExecutionAsync((Func<object, object?[]?, Task>)del, instance, parameters), // 调用节点方法,获取入参参数,返回方法返回类型
// (false, true) => await ExecutionAsync((Func<object, Task<object?>>)del, instance), // 调用节点方法,返回方法传回类型
// (true, true) => await ExecutionAsync((Func<object, object?[]?, Task<object?>>)del, instance, parameters), // 调用节点方法,获取入参参数,返回方法返回类型
// };
//}
//else
//{
// // 非异步方法
// result = (haveParameter, haveResult) switch
// {
// (false, false) => Execution((Action<object>)del, instance), // 调用节点方法, 返回null
// (true, false) => Execution((Action<object, object?[]?>)del, instance, parameters), // 调用节点方法, 返回null
// (false, true) => Execution((Func<object, object?>)del, instance), // 调用节点方法,返回方法传回类型
// (true, true) => Execution((Func<object, object?[]?, object?>)del, instance, parameters), // 调用节点方法,获取入参参数,返回方法返回类型
// };
//}
2024-09-15 22:07:10 +08:00
NextOrientation = ConnectionType . IsSucceed ;
2024-09-09 16:42:01 +08:00
return result ;
}
catch ( Exception ex )
{
2024-10-07 15:15:18 +08:00
await Console . Out . WriteLineAsync ( $"节点[{this.MethodDetails?.MethodName}]异常:" + ex . Message ) ;
2024-09-15 22:07:10 +08:00
NextOrientation = ConnectionType . IsError ;
2024-09-15 12:15:32 +08:00
RuningException = ex ;
2024-09-18 16:45:41 +08:00
return null ;
2024-08-06 16:09:46 +08:00
}
}
2024-09-18 16:45:41 +08:00
#region 节 点 转 换 的 委 托 类 型
public static object? Execution ( Action < object > del , object instance )
{
2024-10-07 22:52:10 +08:00
del . Invoke ( instance ) ;
2024-09-18 16:45:41 +08:00
return null ;
}
public static object? Execution ( Action < object , object? [ ] ? > del , object instance , object? [ ] ? parameters )
{
2024-10-07 22:52:10 +08:00
del . Invoke ( instance , parameters ) ;
2024-09-18 16:45:41 +08:00
return null ;
}
public static object? Execution ( Func < object , object? > del , object instance )
{
2024-10-07 22:52:10 +08:00
return del . Invoke ( instance ) ;
2024-09-18 16:45:41 +08:00
}
public static object? Execution ( Func < object , object? [ ] ? , object? > del , object instance , object? [ ] ? parameters )
{
2024-10-07 22:52:10 +08:00
return del . Invoke ( instance , parameters ) ;
}
public static async Task < object? > ExecutionAsync ( Func < object , Task > del , object instance )
{
await del . Invoke ( instance ) ;
return null ;
}
public static async Task < object? > ExecutionAsync ( Func < object , object? [ ] ? , Task > del , object instance , object? [ ] ? parameters )
{
await del . Invoke ( instance , parameters ) ;
return null ;
}
public static async Task < object? > ExecutionAsync ( Func < object , Task < object? > > del , object instance )
{
return await del . Invoke ( instance ) ;
}
public static async Task < object? > ExecutionAsync ( Func < object , object? [ ] ? , Task < object? > > del , object instance , object? [ ] ? parameters )
{
return await del . Invoke ( instance , parameters ) ;
2024-08-06 16:09:46 +08:00
}
2024-09-18 16:45:41 +08:00
#endregion
2024-08-06 16:09:46 +08:00
2024-09-09 16:42:01 +08:00
/// <summary>
/// 获取对应的参数数组
/// </summary>
2024-09-22 14:10:13 +08:00
public static object? [ ] ? GetParameters ( IDynamicContext context , NodeModelBase nodeModel , MethodDetails md )
2024-08-06 16:09:46 +08:00
{
// 用正确的大小初始化参数数组
2024-09-20 10:50:32 +08:00
if ( md . ExplicitDatas . Length = = 0 )
2024-08-06 16:09:46 +08:00
{
2024-09-21 10:06:44 +08:00
return null ; // md.ActingInstance
2024-08-06 16:09:46 +08:00
}
2024-09-20 10:50:32 +08:00
object? [ ] ? parameters = new object [ md . ExplicitDatas . Length ] ;
2024-09-22 14:10:13 +08:00
var flowData = nodeModel . PreviousNode ? . FlowData ; // 当前传递的数据
2024-09-18 16:45:41 +08:00
var previousDataType = flowData ? . GetType ( ) ;
2024-08-06 16:09:46 +08:00
2024-09-20 10:50:32 +08:00
for ( int i = 0 ; i < parameters . Length ; i + + )
2024-08-06 16:09:46 +08:00
{
2024-09-20 10:50:32 +08:00
object? inputParameter ; // 存放解析的临时参数
2024-09-18 16:45:41 +08:00
var ed = md . ExplicitDatas [ i ] ; // 方法入参描述
2024-09-20 10:50:32 +08:00
2024-09-27 10:30:19 +08:00
if ( ed . IsExplicitData ) // 判断是否使用显示的输入参数
2024-08-06 16:09:46 +08:00
{
2024-09-30 22:20:02 +08:00
if ( ed . DataValue . StartsWith ( "@get" , StringComparison . OrdinalIgnoreCase ) & & flowData is not null )
2024-09-18 23:03:35 +08:00
{
// 执行表达式从上一节点获取对象
2024-09-20 10:50:32 +08:00
inputParameter = SerinExpressionEvaluator . Evaluate ( ed . DataValue , flowData , out _ ) ;
2024-09-18 23:03:35 +08:00
}
2024-09-20 10:50:32 +08:00
else
2024-09-18 23:03:35 +08:00
{
// 使用输入的固定值
2024-09-20 10:50:32 +08:00
inputParameter = ed . DataValue ;
2024-09-18 23:03:35 +08:00
}
2024-08-06 16:09:46 +08:00
}
2024-09-18 16:45:41 +08:00
else
2024-08-06 16:09:46 +08:00
{
2024-09-18 16:45:41 +08:00
inputParameter = flowData ; // 使用上一节点的对象
2024-08-06 16:09:46 +08:00
}
2024-09-12 20:32:54 +08:00
2024-09-28 23:55:19 +08:00
// 存在转换器
if ( ed . Convertor is not null )
{
if ( Enum . TryParse ( ed . ExplicitType , ed . DataValue , out var resultEnum ) )
{
var value = ed . Convertor ( resultEnum ) ;
if ( value is not null )
{
parameters [ i ] = value ;
continue ;
}
else
{
throw new InvalidOperationException ( "转换器调用失败" ) ;
}
}
}
2024-09-27 10:30:19 +08:00
if ( ed . DataType ! = ed . ExplicitType ) // 获取枚举转换器中记录的枚举
{
if ( ed . ExplicitType . IsEnum & & Enum . TryParse ( ed . ExplicitType , ed . DataValue , out var resultEnum ) ) // 获取对应的枚举项
{
var type = EnumHelper . GetBoundValue ( ed . ExplicitType , resultEnum , attr = > attr . Value ) ;
if ( type is Type enumBindType & & enumBindType is not null )
{
var value = context . Env . IOC . Instantiate ( enumBindType ) ;
if ( value is not null )
{
parameters [ i ] = value ;
continue ;
}
}
}
}
2024-09-28 23:55:19 +08:00
2024-09-27 10:30:19 +08:00
2024-09-18 16:45:41 +08:00
try
2024-08-06 16:09:46 +08:00
{
2024-10-10 16:49:37 +08:00
if ( ed . DataType . IsValueType )
2024-09-12 20:32:54 +08:00
{
2024-10-10 16:49:37 +08:00
if ( inputParameter is null )
{
parameters [ i ] = Activator . CreateInstance ( ed . DataType ) ;
}
else
{
string? valueStr = inputParameter ? . ToString ( ) ;
if ( string . IsNullOrEmpty ( valueStr ) )
{
parameters [ i ] = Activator . CreateInstance ( ed . DataType ) ;
}
else
{
parameters [ i ] = ed . DataType switch
{
Type t when t . IsEnum = > Enum . Parse ( ed . DataType , ed . DataValue ) , // 需要枚举
Type t when t = = typeof ( char ) = > char . Parse ( valueStr ) ,
Type t when t = = typeof ( bool ) = > bool . Parse ( valueStr ) ,
Type t when t = = typeof ( float ) = > float . Parse ( valueStr ) ,
Type t when t = = typeof ( decimal ) = > decimal . Parse ( valueStr ) ,
Type t when t = = typeof ( double ) = > double . Parse ( valueStr ) ,
Type t when t = = typeof ( sbyte ) = > sbyte . Parse ( valueStr ) ,
Type t when t = = typeof ( byte ) = > byte . Parse ( valueStr ) ,
Type t when t = = typeof ( short ) = > short . Parse ( valueStr ) ,
Type t when t = = typeof ( ushort ) = > ushort . Parse ( valueStr ) ,
Type t when t = = typeof ( int ) = > int . Parse ( valueStr ) ,
Type t when t = = typeof ( uint ) = > uint . Parse ( valueStr ) ,
Type t when t = = typeof ( long ) = > long . Parse ( valueStr ) ,
Type t when t = = typeof ( ulong ) = > ulong . Parse ( valueStr ) ,
Type t when t = = typeof ( nint ) = > nint . Parse ( valueStr ) ,
Type t when t = = typeof ( nuint ) = > nuint . Parse ( valueStr ) ,
_ = > throw new Exception ( $"调用节点对应方法[{nodeModel.MethodDetails.MethodName}]时,遇到了未在预期内的值类型入参:{ed.DataType.FullName}" ) ,
// Type t when Nullable.GetUnderlyingType(t) != null => inputParameter is null ? null : Convert.ChangeType(inputParameter, Nullable.GetUnderlyingType(t)),
} ;
}
}
}
else
{
parameters [ i ] = ed . DataType switch
{
Type t when t = = typeof ( IDynamicContext ) = > context , // 上下文
Type t when t = = typeof ( string ) = > inputParameter ? . ToString ( ) ,
//Type t when t == typeof(DateTime) => string.IsNullOrEmpty(valueStr) ? 0 : DateTime.Parse(valueStr),
Type t when t = = typeof ( MethodDetails ) = > md , // 节点方法描述
Type t when t = = typeof ( NodeModelBase ) = > nodeModel , // 节点实体类
Type t when t . IsArray = > ( inputParameter as Array ) ? . Cast < object > ( ) . ToList ( ) ,
Type t when t . IsGenericType & & t . GetGenericTypeDefinition ( ) = = typeof ( List < > ) = > inputParameter ,
_ = > inputParameter ,
// Type t when Nullable.GetUnderlyingType(t) != null => inputParameter is null ? null : Convert.ChangeType(inputParameter, Nullable.GetUnderlyingType(t)),
} ;
}
2024-09-30 22:20:02 +08:00
2024-08-06 16:09:46 +08:00
}
2024-09-18 16:45:41 +08:00
catch ( Exception ex ) // 节点参数类型转换异常
2024-08-06 16:09:46 +08:00
{
2024-09-30 22:20:02 +08:00
parameters [ i ] = new object ( ) ;
2024-09-18 16:45:41 +08:00
Console . WriteLine ( ex ) ;
2024-08-06 16:09:46 +08:00
}
}
return parameters ;
}
2024-09-22 14:10:13 +08:00
/// <summary>
2024-09-24 22:39:43 +08:00
/// 更新节点数据,并检查监视表达式是否生效
2024-09-22 14:10:13 +08:00
/// </summary>
/// <param name="newData"></param>
2024-09-24 22:39:43 +08:00
public static async Task RefreshFlowDataAndExpInterrupt ( IDynamicContext context , NodeModelBase nodeModel , object? newData = null )
2024-09-22 14:10:13 +08:00
{
string guid = nodeModel . Guid ;
2024-09-24 22:39:43 +08:00
if ( newData is not null )
2024-09-22 14:10:13 +08:00
{
2024-09-24 22:39:43 +08:00
await MonitorObjExpInterrupt ( context , nodeModel , newData , 0 ) ; // 首先监视对象
await MonitorObjExpInterrupt ( context , nodeModel , newData , 1 ) ; // 然后监视节点
nodeModel . FlowData = newData ; // 替换数据
}
}
2024-09-30 22:20:02 +08:00
private static async Task MonitorObjExpInterrupt ( IDynamicContext context , NodeModelBase nodeModel , object? data , int monitorType )
2024-09-24 22:39:43 +08:00
{
MonitorObjectEventArgs . ObjSourceType sourceType ;
2024-09-30 22:20:02 +08:00
string? key ;
if ( monitorType = = 0 )
2024-09-22 14:10:13 +08:00
{
2024-09-30 22:20:02 +08:00
key = data ? . GetType ( ) ? . FullName ;
2024-09-24 22:39:43 +08:00
sourceType = MonitorObjectEventArgs . ObjSourceType . IOCObj ;
}
else
{
key = nodeModel . Guid ;
sourceType = MonitorObjectEventArgs . ObjSourceType . IOCObj ;
2024-09-22 14:10:13 +08:00
}
2024-09-30 22:20:02 +08:00
if ( string . IsNullOrEmpty ( key ) )
{
return ;
}
2024-09-24 22:39:43 +08:00
if ( context . Env . CheckObjMonitorState ( key , out List < string > exps ) ) // 如果新的数据处于查看状态, 通知UI进行更新? 交给运行环境判断?
{
context . Env . MonitorObjectNotification ( nodeModel . Guid , data , sourceType ) ; // 对象处于监视状态, 通知UI更新数据显示
if ( exps . Count > 0 )
{
// 表达式环境下判断是否需要执行中断
bool isExpInterrupt = false ;
string? exp = "" ;
// 判断执行监视表达式,直到为 true 时退出
for ( int i = 0 ; i < exps . Count & & ! isExpInterrupt ; i + + )
{
exp = exps [ i ] ;
2024-09-26 21:00:17 +08:00
if ( string . IsNullOrEmpty ( exp ) ) continue ;
2024-09-24 22:39:43 +08:00
isExpInterrupt = SereinConditionParser . To ( data , exp ) ;
}
if ( isExpInterrupt ) // 触发中断
{
InterruptClass interruptClass = InterruptClass . Branch ; // 分支中断
if ( context . Env . SetNodeInterrupt ( nodeModel . Guid , interruptClass ) )
{
2024-09-26 21:00:17 +08:00
context . Env . TriggerInterrupt ( nodeModel . Guid , exp , InterruptTriggerEventArgs . InterruptTriggerType . Exp ) ;
2024-09-24 22:39:43 +08:00
var cancelType = await nodeModel . DebugSetting . GetInterruptTask ( ) ;
await Console . Out . WriteLineAsync ( $"[{data}]中断已{cancelType},开始执行后继分支" ) ;
}
}
}
2024-09-22 14:10:13 +08:00
2024-09-24 22:39:43 +08:00
}
2024-09-22 14:10:13 +08:00
}
2024-09-24 22:39:43 +08:00
2024-09-22 14:10:13 +08:00
/// <summary>
/// 释放对象
/// </summary>
public void ReleaseFlowData ( )
{
if ( typeof ( IDisposable ) . IsAssignableFrom ( FlowData ? . GetType ( ) ) & & FlowData is IDisposable disposable )
{
disposable ? . Dispose ( ) ;
}
this . FlowData = null ;
}
/// <summary>
/// 获取节点数据
/// </summary>
/// <returns></returns>
public object? GetFlowData ( )
{
2024-09-22 17:37:32 +08:00
return this . FlowData ;
2024-09-22 14:10:13 +08:00
}
2024-09-20 10:50:32 +08:00
#endregion
2024-08-06 16:09:46 +08:00
}
}