using Newtonsoft.Json; using Serein.Library.Api; using Serein.Library.Entity; using Serein.Library.Enums; using Serein.Library.Ex; using Serein.NodeFlow.Tool.SereinExpression; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Serein.NodeFlow.Base { /// /// 节点基类(数据):条件控件,动作控件,条件区域,动作区域 /// public abstract partial class NodeModelBase : IDynamicFlowNode { internal abstract Parameterdata[] GetParameterdatas(); internal virtual NodeInfo ToInfo() { // if (MethodDetails == null) return null; var trueNodes = SuccessorNodes[ConnectionType.IsSucceed].Select(item => item.Guid); // 真分支 var falseNodes = SuccessorNodes[ConnectionType.IsFail].Select(item => item.Guid);// 假分支 var errorNodes = SuccessorNodes[ConnectionType.IsError].Select(item => item.Guid);// 异常分支 var upstreamNodes = SuccessorNodes[ConnectionType.Upstream].Select(item => item.Guid);// 上游分支 // 生成参数列表 Parameterdata[] parameterData = GetParameterdatas(); 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(), }; } internal virtual NodeModelBase LoadInfo(NodeInfo nodeInfo) { var node = this; if (node != null) { node.Guid = nodeInfo.Guid; for (int i = 0; i < nodeInfo.ParameterData.Length; i++) { Parameterdata? pd = nodeInfo.ParameterData[i]; node.MethodDetails.ExplicitDatas[i].IsExplicitData = pd.State; node.MethodDetails.ExplicitDatas[i].DataValue = pd.Value; } } //if (control is ConditionNodeControl conditionNodeControl) //{ // conditionNodeControl.ViewModel.IsCustomData = pd.state; // conditionNodeControl.ViewModel.CustomData = pd.value; // conditionNodeControl.ViewModel.Expression = pd.expression; //} //else if (control is ExpOpNodeControl expOpNodeControl) //{ // expOpNodeControl.ViewModel.Expression = pd.expression; //} //else //{ // node.MethodDetails.ExplicitDatas[i].IsExplicitData = pd.state; // node.MethodDetails.ExplicitDatas[i].DataValue = pd.value; //} return this; } /// /// 开始执行 /// /// /// public async Task StartExecution(IDynamicContext context) { var cts = context.SereinIoc.GetOrRegisterInstantiate(); Stack stack = []; stack.Push(this); while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环 { // 从栈中弹出一个节点作为当前节点进行处理 var currentNode = stack.Pop(); // 设置方法执行的对象 if (currentNode.MethodDetails is not null && currentNode.MethodDetails.ActingInstanceType is not null) { // currentNode.MethodDetails.ActingInstance ??= context.SereinIoc.GetOrInstantiate(MethodDetails.ActingInstanceType); // currentNode.MethodDetails.ActingInstance = context.SereinIoc.GetOrInstantiate(MethodDetails.ActingInstanceType); currentNode.MethodDetails.ActingInstance = context.SereinIoc.GetOrRegisterInstantiate(currentNode.MethodDetails.ActingInstanceType); } // 获取上游分支,首先执行一次 var upstreamNodes = currentNode.SuccessorNodes[ConnectionType.Upstream]; for (int i = upstreamNodes.Count - 1; i >= 0; i--) { upstreamNodes[i].PreviousNode = currentNode; await upstreamNodes[i].StartExecution(context); } if (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == NodeType.Flipflop) { // 触发器节点 currentNode.FlowData = await currentNode.ExecuteAsync(context); } else { // 动作节点 currentNode.FlowData = currentNode.Execute(context); } if(currentNode.NextOrientation == ConnectionType.None) { // 不再执行 break; } var nextNodes = currentNode.SuccessorNodes[currentNode.NextOrientation]; // 将下一个节点集合中的所有节点逆序推入栈中 for (int i = nextNodes.Count - 1; i >= 0; i--) { nextNodes[i].PreviousNode = currentNode; stack.Push(nextNodes[i]); } } } /// /// 执行节点对应的方法 /// /// 流程上下文 /// 节点传回数据对象 public virtual object? Execute(IDynamicContext context) { MethodDetails md = MethodDetails; object? result = null; var del = md.MethodDelegate; try { if (md.ExplicitDatas.Length == 0) { if (md.ReturnType == typeof(void)) { ((Action)del).Invoke(md.ActingInstance); } else { result = ((Func)del).Invoke(md.ActingInstance); } } else { object?[]? parameters = GetParameters(context, MethodDetails); if (md.ReturnType == typeof(void)) { ((Action)del).Invoke(md.ActingInstance, parameters); } else { var func = del as Func; //result = ((Func)del).Invoke(md.ActingInstance, parameters); result = func?.Invoke(md.ActingInstance, parameters); } } NextOrientation = ConnectionType.IsSucceed; return result; } catch (Exception ex) { NextOrientation = ConnectionType.IsError; RuningException = ex; } return result; } /// /// 执行等待触发器的方法 /// /// /// 节点传回数据对象 /// public virtual async Task ExecuteAsync(IDynamicContext context) { MethodDetails md = MethodDetails; object? result = null; IFlipflopContext flipflopContext = null; try { // 调用委托并获取结果 if (md.ExplicitDatas.Length == 0) { flipflopContext = await ((Func>)md.MethodDelegate).Invoke(MethodDetails.ActingInstance); } else { object?[]? parameters = GetParameters(context, MethodDetails); flipflopContext = await ((Func>)md.MethodDelegate).Invoke(MethodDetails.ActingInstance, parameters); } if (flipflopContext == null) { throw new FlipflopException("没有返回上下文"); } NextOrientation = flipflopContext.State.ToContentType(); result = flipflopContext.Data; } catch (Exception ex) { NextOrientation = ConnectionType.IsError; RuningException = ex; } return result; } /// /// 获取对应的参数数组 /// public object[]? GetParameters(IDynamicContext context, MethodDetails md) { // 用正确的大小初始化参数数组 var types = md.ExplicitDatas.Select(it => it.DataType).ToArray(); if (types.Length == 0) { return [md.ActingInstance]; } object[]? parameters = new object[types.Length]; for (int i = 0; i < types.Length; i++) { var mdEd = md.ExplicitDatas[i]; Type type = mdEd.DataType; var f1 = PreviousNode?.FlowData?.GetType(); var f2 = mdEd.DataType; if (type == typeof(IDynamicContext)) { parameters[i] = context; } else if (type == typeof(MethodDetails)) { parameters[i] = md; } else if (type == typeof(NodeModelBase)) { parameters[i] = this; } else if (mdEd.IsExplicitData) // 显式参数 { // 判断是否使用表达式解析 if (mdEd.DataValue[0] == '@') { var expResult = SerinExpressionEvaluator.Evaluate(mdEd.DataValue, PreviousNode?.FlowData, out bool isChange); if (mdEd.DataType.IsEnum) { var enumValue = Enum.Parse(mdEd.DataType, mdEd.DataValue); parameters[i] = enumValue; } else if (mdEd.ExplicitType == typeof(string)) { parameters[i] = Convert.ChangeType(expResult, typeof(string)); } else if (mdEd.ExplicitType == typeof(bool)) { parameters[i] = Convert.ChangeType(expResult, typeof(bool)); } else if (mdEd.ExplicitType == typeof(int)) { parameters[i] = Convert.ChangeType(expResult, typeof(int)); } else if (mdEd.ExplicitType == typeof(double)) { parameters[i] = Convert.ChangeType(expResult, typeof(double)); } else { parameters[i] = expResult; //parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType); } } else { if (mdEd.DataType.IsEnum) { var enumValue = Enum.Parse(mdEd.DataType, mdEd.DataValue); parameters[i] = enumValue; } else if (mdEd.ExplicitType == typeof(string)) { parameters[i] = mdEd.DataValue; } else if (mdEd.ExplicitType == typeof(bool)) { parameters[i] = bool.Parse(mdEd.DataValue); } else if (mdEd.ExplicitType == typeof(int)) { parameters[i] = int.Parse(mdEd.DataValue); } else if (mdEd.ExplicitType == typeof(double)) { parameters[i] = double.Parse(mdEd.DataValue); } else { parameters[i] = ""; //parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType); } } } else if (f1 != null && f2 != null) { if (f2.IsAssignableFrom(f1) || f2.FullName.Equals(f1.FullName)) { parameters[i] = PreviousNode?.FlowData; } } else { var tmpParameter = PreviousNode?.FlowData?.ToString(); if (mdEd.DataType.IsEnum) { var enumValue = Enum.Parse(mdEd.DataType, tmpParameter); parameters[i] = enumValue; } else if (mdEd.DataType == typeof(string)) { parameters[i] = tmpParameter; } else if (mdEd.DataType == typeof(bool)) { parameters[i] = bool.Parse(tmpParameter); } else if (mdEd.DataType == typeof(int)) { parameters[i] = int.Parse(tmpParameter); } else if (mdEd.DataType == typeof(double)) { parameters[i] = double.Parse(tmpParameter); } else { if (tmpParameter != null && mdEd.DataType != null) { parameters[i] = ConvertValue(tmpParameter, mdEd.DataType); } } } } return parameters; } /// /// json文本反序列化为对象 /// /// /// /// private dynamic? ConvertValue(string value, Type targetType) { try { if (!string.IsNullOrEmpty(value)) { return JsonConvert.DeserializeObject(value, targetType); } else { return null; } } catch (JsonReaderException ex) { Console.WriteLine(ex); return value; } catch (JsonSerializationException ex) { // 如果无法转为对应的JSON对象 int startIndex = ex.Message.IndexOf("to type '") + "to type '".Length; // 查找类型信息开始的索引 int endIndex = ex.Message.IndexOf('\''); // 查找类型信息结束的索引 var typeInfo = ex.Message[startIndex..endIndex]; // 提取出错类型信息,该怎么传出去? Console.WriteLine("无法转为对应的JSON对象:" + typeInfo); return null; } catch // (Exception ex) { return value; } } #region 完整的ExecuteAsync调用方法(不要删除) //public virtual async Task ExecuteAsync(DynamicContext context) //{ // MethodDetails md = MethodDetails; // object? result = null; // if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del)) // { // if (md.ExplicitDatas.Length == 0) // { // if (md.ReturnType == typeof(void)) // { // ((Action)del).Invoke(md.ActingInstance); // } // else if (md.ReturnType == typeof(Task)) // { // // 调用委托并获取结果 // FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance); // if (flipflopContext != null) // { // if (flipflopContext.State == FfState.Cancel) // { // throw new Exception("this async task is cancel."); // } // else // { // if (flipflopContext.State == FfState.Succeed) // { // CurrentState = true; // result = flipflopContext.Data; // } // else // { // CurrentState = false; // } // } // } // } // else // { // result = ((Func)del).Invoke(md.ActingInstance); // } // } // else // { // object?[]? parameters = GetParameters(context, MethodDetails); // if (md.ReturnType == typeof(void)) // { // ((Action)del).Invoke(md.ActingInstance, parameters); // } // else if (md.ReturnType == typeof(Task)) // { // // 调用委托并获取结果 // FlipflopContext flipflopContext = await ((Func>)del).Invoke(MethodDetails.ActingInstance, parameters); // if (flipflopContext != null) // { // if (flipflopContext.State == FfState.Cancel) // { // throw new Exception("取消此异步"); // } // else // { // CurrentState = flipflopContext.State == FfState.Succeed; // result = flipflopContext.Data; // } // } // } // else // { // result = ((Func)del).Invoke(md.ActingInstance, parameters); // } // } // context.SetFlowData(result); // } // return result; //} #endregion } }