From 1e09675ef1e175a50ecd620e6c21745183f30c2e Mon Sep 17 00:00:00 2001 From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com> Date: Fri, 14 Mar 2025 21:38:07 +0800 Subject: [PATCH] =?UTF-8?q?=E8=84=9A=E6=9C=AC=E8=8A=82=E7=82=B9=E8=83=BD?= =?UTF-8?q?=E5=A4=9F=E8=87=AA=E5=AE=9A=E4=B9=89=E5=8F=98=E9=87=8F=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/FlowNode/NodeModelBaseFunc.cs | 2 + Library/FlowNode/ParameterDetails.cs | 2 +- Library/FlowNode/SereinProjectData.cs | 13 ++-- NodeFlow/Model/SingleScriptNode.cs | 55 ++++++++++---- Serein.Script/Node/AssignmentNode.cs | 9 ++- Serein.Script/SereinScriptInterpreter.cs | 4 +- Workbench/Themes/MethodDetailsControl.xaml | 74 +++++++++++++++++-- Workbench/Themes/MethodDetailsControl.xaml.cs | 31 +++++++- .../Tool/Converters/EnumToBooleanConverter.cs | 27 +++++++ 9 files changed, 188 insertions(+), 29 deletions(-) create mode 100644 Workbench/Tool/Converters/EnumToBooleanConverter.cs diff --git a/Library/FlowNode/NodeModelBaseFunc.cs b/Library/FlowNode/NodeModelBaseFunc.cs index ff5c09c..d0a5a05 100644 --- a/Library/FlowNode/NodeModelBaseFunc.cs +++ b/Library/FlowNode/NodeModelBaseFunc.cs @@ -110,7 +110,9 @@ namespace Serein.Library SourceNodeGuid = it.ArgDataSourceNodeGuid, SourceType = it.ArgDataSourceType.ToString(), State = it.IsExplicitData, + ArgName = it.Name, Value = it.DataValue, + }) .ToArray(); } diff --git a/Library/FlowNode/ParameterDetails.cs b/Library/FlowNode/ParameterDetails.cs index f3065a5..9978424 100644 --- a/Library/FlowNode/ParameterDetails.cs +++ b/Library/FlowNode/ParameterDetails.cs @@ -81,7 +81,7 @@ namespace Serein.Library /// /// 方法入参参数名称 /// - [PropertyInfo] + [PropertyInfo(IsNotification = true)] private string _name ; /// diff --git a/Library/FlowNode/SereinProjectData.cs b/Library/FlowNode/SereinProjectData.cs index 4b7cd9b..c825c96 100644 --- a/Library/FlowNode/SereinProjectData.cs +++ b/Library/FlowNode/SereinProjectData.cs @@ -277,11 +277,13 @@ namespace Serein.Library /// public class ParameterData { + /// /// 参数类型,true时使用自定义的入参,false时由运行环境自动传参 /// public bool State { get; set; } + /// /// 参数来源节点 /// @@ -292,16 +294,17 @@ namespace Serein.Library /// public string SourceType { get; set; } + + /// + /// 参数名称 + /// + public string ArgName { get; set; } + /// /// 自定义入参 /// public string Value { get; set; } - /// - /// 表达式相关节点的表达式内容 - /// - // public string Expression { get; set; } - } diff --git a/NodeFlow/Model/SingleScriptNode.cs b/NodeFlow/Model/SingleScriptNode.cs index e0bd450..4152264 100644 --- a/NodeFlow/Model/SingleScriptNode.cs +++ b/NodeFlow/Model/SingleScriptNode.cs @@ -66,6 +66,7 @@ namespace Serein.NodeFlow.Model } } + public override void OnCreating() { MethodInfo? method = this.GetType().GetMethod(nameof(GetFlowApi)); @@ -115,6 +116,14 @@ namespace Serein.NodeFlow.Model public override void LoadCustomData(NodeInfo nodeInfo) { this.Script = nodeInfo.CustomData?.Script ?? ""; + + // 更新变量名 + for (int i = 0; i < Math.Min(this.MethodDetails.ParameterDetailss.Length, nodeInfo.ParameterData.Length); i++) + { + this.MethodDetails.ParameterDetailss[i].Name = nodeInfo.ParameterData[i].ArgName; + } + + } /// @@ -124,12 +133,30 @@ namespace Serein.NodeFlow.Model { try { + HashSet varNames = new HashSet(); + foreach (var pd in MethodDetails.ParameterDetailss) + { + if (varNames.Contains(pd.Name)) + { + throw new Exception($"脚本节点重复的变量名称:{pd.Name} - {Guid}"); + } + varNames.Add(pd.Name); + } + + //StringBuilder sb = new StringBuilder(); + //foreach (var pd in MethodDetails.ParameterDetailss) + //{ + // sb.AppendLine($"let {pd.Name};"); // 提前声明这些变量 + //} + //sb.Append(Script); + //var p = new SereinScriptParser(sb.ToString()); var p = new SereinScriptParser(Script); - mainNode = p.Parse(); + mainNode = p.Parse(); // 开始解析 } catch (Exception ex) { SereinEnv.WriteLine(InfoType.ERROR, ex.ToString()); + } } @@ -141,21 +168,23 @@ namespace Serein.NodeFlow.Model public override async Task ExecutingAsync(IDynamicContext context) { var @params = await GetParametersAsync(context); - //dynamic obj = ((object[])@params[0])[0]; - //try - //{ - // SereinEnv.WriteLine(InfoType.INFO, "Dynamic Object Value :" + obj.VarInfo); - //} - //catch (Exception ex) - //{ - // SereinEnv.WriteLine(ex); - //} - //ScriptFlowApi.Context = context; // 并发破坏了数据状态 - context.AddOrUpdate($"{context.Guid}_{this.Guid}_Params", @params[0]); // 后面再改 - mainNode ??= new SereinScriptParser(Script).Parse(); + //context.AddOrUpdate($"{context.Guid}_{this.Guid}_Params", @params[0]); // 后面再改 + ReloadScript();// 每次都重新解析 + IScriptInvokeContext scriptContext = new ScriptInvokeContext(context); + if (@params[0] is object[] agrDatas) + { + for (int i = 0; i < agrDatas.Length; i++) + { + var argName = MethodDetails.ParameterDetailss[i].Name; + var argData = agrDatas[i]; + scriptContext.SetVarValue(argName, argData); + } + } + + var result = await ScriptInterpreter.InterpretAsync(scriptContext, mainNode); // 从入口节点执行 //SereinEnv.WriteLine(InfoType.INFO, "FlowContext Guid : " + context.Guid); return result; diff --git a/Serein.Script/Node/AssignmentNode.cs b/Serein.Script/Node/AssignmentNode.cs index a5f731b..d6b3237 100644 --- a/Serein.Script/Node/AssignmentNode.cs +++ b/Serein.Script/Node/AssignmentNode.cs @@ -8,12 +8,19 @@ namespace Serein.Script.Node { /// - /// 变量节点 + /// 赋值节点 /// public class AssignmentNode : ASTNode { + /// + /// 变量名称 + /// public string Variable { get; } + /// + /// 对应的节点 + /// public ASTNode Value { get; } + public AssignmentNode(string variable, ASTNode value) => (Variable, Value) = (variable, value); } diff --git a/Serein.Script/SereinScriptInterpreter.cs b/Serein.Script/SereinScriptInterpreter.cs index a1ecace..9bb68a0 100644 --- a/Serein.Script/SereinScriptInterpreter.cs +++ b/Serein.Script/SereinScriptInterpreter.cs @@ -212,6 +212,8 @@ namespace Serein.Script /// private async Task ExecutionProgramNodeAsync(IScriptInvokeContext context, ProgramNode programNode) { + // 加载变量 + // 遍历 ProgramNode 中的所有语句并执行它们 foreach (var statement in programNode.Statements) { @@ -366,8 +368,6 @@ namespace Serein.Script } - - public async Task InterpretAsync(IScriptInvokeContext context, ASTNode node) { if(node == null) diff --git a/Workbench/Themes/MethodDetailsControl.xaml b/Workbench/Themes/MethodDetailsControl.xaml index 71259a4..d83ca71 100644 --- a/Workbench/Themes/MethodDetailsControl.xaml +++ b/Workbench/Themes/MethodDetailsControl.xaml @@ -3,12 +3,17 @@ xmlns:local="clr-namespace:Serein.Workbench.Themes" xmlns:view="clr-namespace:Serein.Workbench.Node.View" xmlns:sys="clr-namespace:System;assembly=mscorlib" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:serein="clr-namespace:Serein.Library;assembly=Serein.Library" xmlns:converters="clr-namespace:Serein.Workbench.Tool.Converters"> + + + + + + + /> diff --git a/Workbench/Themes/MethodDetailsControl.xaml.cs b/Workbench/Themes/MethodDetailsControl.xaml.cs index 32caab5..8dc2b20 100644 --- a/Workbench/Themes/MethodDetailsControl.xaml.cs +++ b/Workbench/Themes/MethodDetailsControl.xaml.cs @@ -39,6 +39,29 @@ namespace Serein.Workbench.Themes } + public class DataContextProxy : Freezable + { + public DataContextProxy() + { + BindingOperations.SetBinding(this, DataContextProperty, new Binding()); + } + + public ParameterDetails DataContext + { + get { return (ParameterDetails)GetValue(DataContextProperty); } + set { SetValue(DataContextProperty, value); } + } + + + public static readonly DependencyProperty DataContextProperty = FrameworkElement + .DataContextProperty.AddOwner(typeof(DataContextProxy)); + + protected override Freezable CreateInstanceCore() + { + return new DataContextProxy(); + } + } + /// /// 方法参数控件 @@ -78,13 +101,17 @@ namespace Serein.Workbench.Themes CommandAddParams = new RelayCommand(ExecuteAddParams); } + + private void ExecuteAddParams(object parameter) { // 方法逻辑 this.MethodDetails.AddParamsArg(); } - - + } + + + } diff --git a/Workbench/Tool/Converters/EnumToBooleanConverter.cs b/Workbench/Tool/Converters/EnumToBooleanConverter.cs new file mode 100644 index 0000000..73f692e --- /dev/null +++ b/Workbench/Tool/Converters/EnumToBooleanConverter.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace Serein.Workbench.Tool.Converters +{ + public class EnumToBooleanConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null || parameter == null) + return false; + + return value.ToString().Equals(parameter.ToString(), StringComparison.InvariantCultureIgnoreCase); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + +}