diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index 5b50ab8..35541c3 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -698,9 +698,10 @@ namespace Serein.Library.Api /// /// 立刻调用某个节点,并获取其返回值 /// + /// 调用时的上下文 /// 节点Guid /// - Task InvokeNodeAsync(string nodeGuid); + Task InvokeNodeAsync(IDynamicContext context, string nodeGuid); /// /// 结束运行 diff --git a/Library/FlowNode/NodeModelBaseFunc.cs b/Library/FlowNode/NodeModelBaseFunc.cs index 93799b8..9c21502 100644 --- a/Library/FlowNode/NodeModelBaseFunc.cs +++ b/Library/FlowNode/NodeModelBaseFunc.cs @@ -325,15 +325,15 @@ namespace Serein.Library for (int i = 0; i < parameters.Length; i++) { - var ed = md.ParameterDetailss[i]; // 方法入参描述 + var pd = md.ParameterDetailss[i]; // 方法入参描述 #region 获取基础的上下文数据 - if (ed.DataType == typeof(IFlowEnvironment)) // 获取流程上下文 + if (pd.DataType == typeof(IFlowEnvironment)) // 获取流程上下文 { parameters[i] = nodeModel.Env; continue; } - if (ed.DataType == typeof(IDynamicContext)) // 获取流程上下文 + if (pd.DataType == typeof(IDynamicContext)) // 获取流程上下文 { parameters[i] = context; continue; @@ -342,41 +342,41 @@ namespace Serein.Library #region 确定[预入参]数据 object inputParameter; // 存放解析的临时参数 - if (ed.IsExplicitData) // 判断是否使用显示的输入参数 + if (pd.IsExplicitData) // 判断是否使用显示的输入参数 { - if (ed.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase)) + if (pd.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase)) { var previousNode = context.GetPreviousNode(nodeModel); var previousFlowData = context.GetFlowData(previousNode.Guid); // 当前传递的数据 // 执行表达式从上一节点获取对象 - inputParameter = SerinExpressionEvaluator.Evaluate(ed.DataValue, previousFlowData, out _); + inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, previousFlowData, out _); } else { // 使用输入的固定值 - inputParameter = ed.DataValue; + inputParameter = pd.DataValue; } } else { - if (ed.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData) + if (pd.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData) { var previousNode = context.GetPreviousNode(nodeModel); inputParameter = context.GetFlowData(previousNode.Guid); // 当前传递的数据 } - else if (ed.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData) + else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData) { // 获取指定节点的数据 // 如果指定节点没有被执行,会返回null // 如果执行过,会获取上一次执行结果作为预入参数据 - inputParameter = context.GetFlowData(ed.ArgDataSourceNodeGuid); + inputParameter = context.GetFlowData(pd.ArgDataSourceNodeGuid); } - else if (ed.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke) + else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke) { // 立刻调用对应节点获取数据。 - var result = await context.Env.InvokeNodeAsync(ed.ArgDataSourceNodeGuid); + var result = await context.Env.InvokeNodeAsync(context, pd.ArgDataSourceNodeGuid); inputParameter = result; } else @@ -386,18 +386,18 @@ namespace Serein.Library } if (inputParameter is null) { - throw new Exception($"[arg{ed.Index}][{ed.Name}][{ed.DataType}]参数不能为null"); + throw new Exception($"[arg{pd.Index}][{pd.Name}][{pd.DataType}]参数不能为null"); } #endregion #region 入参存在取值转换器,调用对应的转换器获取入参数据 // 入参存在取值转换器 - if (ed.ExplicitType.IsEnum && !(ed.Convertor is null)) + if (pd.ExplicitType.IsEnum && !(pd.Convertor is null)) { //var resultEnum = Enum.ToObject(ed.ExplicitType, ed.DataValue); - var resultEnum = Enum.Parse(ed.ExplicitType, ed.DataValue); - var value = ed.Convertor(resultEnum); + var resultEnum = Enum.Parse(pd.ExplicitType, pd.DataValue); + var value = pd.Convertor(resultEnum); if (value is null) { throw new InvalidOperationException("转换器调用失败"); @@ -413,11 +413,11 @@ namespace Serein.Library #region 入参存在基于BinValue的类型转换器,获取枚举转换器中记录的类型 // 入参存在基于BinValue的类型转换器,获取枚举转换器中记录的类型 - if (ed.ExplicitType.IsEnum && ed.DataType != ed.ExplicitType) + if (pd.ExplicitType.IsEnum && pd.DataType != pd.ExplicitType) { - var resultEnum = Enum.Parse(ed.ExplicitType, ed.DataValue); + var resultEnum = Enum.Parse(pd.ExplicitType, pd.DataValue); // 获取绑定的类型 - var type = EnumHelper.GetBoundValue(ed.ExplicitType, resultEnum, attr => attr.Value); + var type = EnumHelper.GetBoundValue(pd.ExplicitType, resultEnum, attr => attr.Value); if (type is Type enumBindType && !(enumBindType is null)) { var value = nodeModel.Env.IOC.Instantiate(enumBindType); @@ -437,30 +437,30 @@ namespace Serein.Library #region 对入参数据尝试进行转换 - if (inputParameter.GetType() == ed.DataType) + if (inputParameter.GetType() == pd.DataType) { parameters[i] = inputParameter; // 类型一致无需转换,直接装入入参数组 } - else if (ed.DataType.IsValueType) + else if (pd.DataType.IsValueType) { // 值类型 var valueStr = inputParameter?.ToString(); - parameters[i] = valueStr.ToValueData(ed.DataType); // 类型不一致,尝试进行转换,如果转换失败返回类型对应的默认值 + parameters[i] = valueStr.ToValueData(pd.DataType); // 类型不一致,尝试进行转换,如果转换失败返回类型对应的默认值 } else { // 引用类型 - if (ed.DataType == typeof(string)) // 转为字符串 + if (pd.DataType == typeof(string)) // 转为字符串 { var valueStr = inputParameter?.ToString(); parameters[i] = valueStr; } - else if(ed.DataType.IsSubclassOf(inputParameter.GetType())) // 入参类型 是 预入参数据类型 的 子类/实现类 + else if(pd.DataType.IsSubclassOf(inputParameter.GetType())) // 入参类型 是 预入参数据类型 的 子类/实现类 { // 方法入参中,父类不能隐式转为子类,这里需要进行强制转换 - parameters[i] = ObjectConvertHelper.ConvertParentToChild(inputParameter, ed.DataType); + parameters[i] = ObjectConvertHelper.ConvertParentToChild(inputParameter, pd.DataType); } - else if(ed.DataType.IsAssignableFrom(inputParameter.GetType())) // 入参类型 是 预入参数据类型 的 父类/接口 + else if(pd.DataType.IsAssignableFrom(inputParameter.GetType())) // 入参类型 是 预入参数据类型 的 父类/接口 { parameters[i] = inputParameter; } @@ -469,12 +469,12 @@ namespace Serein.Library { var enumerableMethods = typeof(Enumerable).GetMethods(); // 获取所有的 Enumerable 扩展方法 MethodInfo conversionMethod; - if (ed.DataType.IsArray) // 转为数组 + if (pd.DataType.IsArray) // 转为数组 { parameters[i] = inputParameter; conversionMethod = enumerableMethods.FirstOrDefault(m => m.Name == "ToArray" && m.IsGenericMethodDefinition); } - else if (ed.DataType.GetGenericTypeDefinition() == typeof(List<>)) // 转为集合 + else if (pd.DataType.GetGenericTypeDefinition() == typeof(List<>)) // 转为集合 { conversionMethod = enumerableMethods.FirstOrDefault(m => m.Name == "ToList" && m.IsGenericMethodDefinition); } @@ -482,7 +482,7 @@ namespace Serein.Library { throw new InvalidOperationException("输入对象不是集合或目标类型不支持(目前仅支持Array、List的自动转换)"); } - var genericMethod = conversionMethod.MakeGenericMethod(ed.DataType); + var genericMethod = conversionMethod.MakeGenericMethod(pd.DataType); var result = genericMethod.Invoke(null, new object[] { collection }); parameters[i] = result; } diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index 76e449b..b4533b1 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -405,15 +405,13 @@ namespace Serein.NodeFlow.Env /// /// /// - public async Task InvokeNodeAsync(string nodeGuid) + public async Task InvokeNodeAsync(IDynamicContext context, string nodeGuid) { - IDynamicContext context = new DynamicContext(this); object result = true; if (this.NodeModels.TryGetValue(nodeGuid, out var model)) { result = await model.InvokeAsync(context); } - context.Exit(); return result; } diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs index 9feddf1..53c7b76 100644 --- a/NodeFlow/Env/FlowEnvironmentDecorator.cs +++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs @@ -364,9 +364,9 @@ namespace Serein.NodeFlow.Env await currentFlowEnvironment.StartAsyncInSelectNode(startNodeGuid); } - public async Task InvokeNodeAsync( string nodeGuid) + public async Task InvokeNodeAsync(IDynamicContext context, string nodeGuid) { - return await currentFlowEnvironment.InvokeNodeAsync( nodeGuid); + return await currentFlowEnvironment.InvokeNodeAsync(context, nodeGuid); } public async Task StartRemoteServerAsync(int port = 7525) diff --git a/NodeFlow/Env/RemoteFlowEnvironment.cs b/NodeFlow/Env/RemoteFlowEnvironment.cs index 673d653..cc52c63 100644 --- a/NodeFlow/Env/RemoteFlowEnvironment.cs +++ b/NodeFlow/Env/RemoteFlowEnvironment.cs @@ -459,7 +459,7 @@ namespace Serein.NodeFlow.Env //UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(nodeGuid,nodeGuid))); } - public async Task InvokeNodeAsync(string nodeGuid) + public async Task InvokeNodeAsync(IDynamicContext context, string nodeGuid) { Console.WriteLine("远程环境尚未实现接口 InvokeNodeAsync"); _ = msgClient.SendAsync(EnvMsgTheme.SetStartNode, new diff --git a/NodeFlow/Model/SingleConditionNode.cs b/NodeFlow/Model/SingleConditionNode.cs index e25ca1e..2225633 100644 --- a/NodeFlow/Model/SingleConditionNode.cs +++ b/NodeFlow/Model/SingleConditionNode.cs @@ -22,8 +22,8 @@ namespace Serein.NodeFlow.Model /// 自定义参数值 /// [PropertyInfo(IsNotification = true)] - private object? _customData; + /// /// 条件表达式 /// @@ -72,32 +72,56 @@ namespace Serein.NodeFlow.Model /// /// /// - public override Task ExecutingAsync(IDynamicContext context) + public override async Task ExecutingAsync(IDynamicContext context) { // 接收上一节点参数or自定义参数内容 object? parameter; - object? result = context.TransmissionData(this); // 条件节点透传上一节点的数据 - if (IsCustomData) // 是否使用自定义参数 + object? result = null; + if (!IsCustomData) // 是否使用自定义参数 { - // 表达式获取上一节点数据 - var getObjExp = CustomData?.ToString(); - if (!string.IsNullOrEmpty(getObjExp) && getObjExp.Length >= 4 && getObjExp[..4].Equals("@get", StringComparison.CurrentCultureIgnoreCase)) + + var pd = MethodDetails.ParameterDetailss[0]; + + if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData) { + // 使用自定义节点的参数 + result = context.GetFlowData(pd.ArgDataSourceNodeGuid); + } + else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke) + { + // 立刻调用目标节点,然后使用其返回值 + result = await Env.InvokeNodeAsync(context, pd.ArgDataSourceNodeGuid); + } + else + { + // 条件节点透传上一节点的数据 + result = context.TransmissionData(this); + } + + // 使用上一节点的参数 + parameter = result; + + } + else + { + + var getObjExp = CustomData?.ToString(); + if (string.IsNullOrEmpty(getObjExp) || getObjExp.Length < 4 || !getObjExp[..4].Equals("@get", StringComparison.CurrentCultureIgnoreCase)) + { + // 使用自定义的参数 + parameter = CustomData; + } + else + { + // 表达式获取上一节点数据 parameter = result; if (parameter is not null) { parameter = SerinExpressionEvaluator.Evaluate(getObjExp, parameter, out _); } } - else - { - parameter = CustomData; - } - } - else - { - parameter = result; } + try { @@ -111,7 +135,7 @@ namespace Serein.NodeFlow.Model } Console.WriteLine($"{result} {Expression} -> " + context.NextOrientation); - return Task.FromResult(result); + return result; } public override ParameterData[] GetParameterdatas()