From 0f46b7ef635b4a3dd63000bbe5a4ac243af4617b Mon Sep 17 00:00:00 2001 From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com> Date: Mon, 9 Dec 2024 22:57:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86@Dtc=EF=BC=88?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2=EF=BC=89?= =?UTF-8?q?=E3=80=81@Data=EF=BC=88=E8=8E=B7=E5=8F=96=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=89=E8=A1=A8=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/Api/IFlowEnvironment.cs | 26 ++++- Library/FlowNode/DelegateDetails.cs | 44 +++---- Library/FlowNode/NodeModelBaseFunc.cs | 34 ++++-- Library/SereinBaseFunction.cs | 65 ++++++++--- Library/Utils/ConvertHelper.cs | 4 + Library/Utils/SereinEnv.cs | 48 +++++++- .../SerinExpressionEvaluator.cs | 108 +++++++++++++++++- NodeFlow/Env/FlowEnvironment.cs | 89 ++++++++++----- NodeFlow/Env/FlowEnvironmentDecorator.cs | 23 ++++ NodeFlow/Env/FlowFunc.cs | 14 ++- NodeFlow/Env/RemoteFlowEnvironment.cs | 25 ++++ NodeFlow/FlowStarter.cs | 11 +- NodeFlow/Model/SingleGlobalDataNode.cs | 30 +++++ NodeFlow/Tool/FlowLibraryManagement.cs | 2 - WorkBench/App.xaml.cs | 3 +- WorkBench/MainWindow.xaml.cs | 4 +- WorkBench/Node/View/ActionNodeControl.xaml | 19 ++- WorkBench/Node/View/ActionNodeControl.xaml.cs | 4 + .../Node/View/ConditionNodeControl.xaml.cs | 1 + .../Node/View/ConditionRegionControl.xaml.cs | 2 - WorkBench/Node/View/ExpOpNodeControl.xaml.cs | 4 +- WorkBench/Serein.WorkBench.csproj | 5 + WorkBench/Themes/MethodDetailsControl.xaml | 1 + Workbench/Node/View/GlobalDataControl.xaml | 75 ++++++++++++ Workbench/Node/View/GlobalDataControl.xaml.cs | 62 ++++++++++ .../ViewModel/ExpOpNodeControlViewModel.cs | 4 +- .../GlobalDataNodeControlViewModel.cs | 18 +++ 27 files changed, 628 insertions(+), 97 deletions(-) create mode 100644 NodeFlow/Model/SingleGlobalDataNode.cs create mode 100644 Workbench/Node/View/GlobalDataControl.xaml create mode 100644 Workbench/Node/View/GlobalDataControl.xaml.cs rename WorkBench/Node/ViewModel/ExpOpNodeViewModel.cs => Workbench/Node/ViewModel/ExpOpNodeControlViewModel.cs (75%) create mode 100644 Workbench/Node/ViewModel/GlobalDataNodeControlViewModel.cs diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index 67108cd..d356e40 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -917,7 +917,30 @@ namespace Serein.Library.Api #endregion - #region 流程依赖类库的接口 + #region 流程运行时 + + #region 全局数据/方法信息 + + + /// + /// 添加或更新全局数据 + /// + /// 数据名称 + /// 数据集 + /// + object AddOrUpdateGlobalData(string keyName, object data); + + /// + /// 获取全局数据 + /// + /// 数据名称 + /// + object GetGlobalData(string keyName); + + #endregion + + + #region 加载依赖 /// /// 运行时加载 @@ -933,6 +956,7 @@ namespace Serein.Library.Api /// 是否递归加载 void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true); + #endregion #endregion #region UI视觉 diff --git a/Library/FlowNode/DelegateDetails.cs b/Library/FlowNode/DelegateDetails.cs index 55c0f83..6d3231c 100644 --- a/Library/FlowNode/DelegateDetails.cs +++ b/Library/FlowNode/DelegateDetails.cs @@ -78,30 +78,34 @@ namespace Serein.Library args = Array.Empty(); } object result = null; - try + if (_emitMethodType == EmitMethodType.HasResultTask && _emitDelegate is Func> hasResultTask) { - if (_emitMethodType == EmitMethodType.HasResultTask && _emitDelegate is Func> hasResultTask) - { - result = await hasResultTask(instance, args); - } - else if (_emitMethodType == EmitMethodType.Task && _emitDelegate is Func task) - { - await task.Invoke(instance, args); - } - else if (_emitMethodType == EmitMethodType.Func && _emitDelegate is Func func) - { - result = func.Invoke(instance, args); - } - else - { - throw new NotImplementedException("创建了非预期委托(应该不会出现)"); - } - return result; + result = await hasResultTask(instance, args); } - catch + else if (_emitMethodType == EmitMethodType.Task && _emitDelegate is Func task) { - throw; + await task.Invoke(instance, args); } + else if (_emitMethodType == EmitMethodType.Func && _emitDelegate is Func func) + { + result = func.Invoke(instance, args); + } + else + { + throw new NotImplementedException("创建了非预期委托(应该不会出现)"); + } + + // + return result; + + //try + //{ + + //} + //catch + //{ + // throw; + //} } } } diff --git a/Library/FlowNode/NodeModelBaseFunc.cs b/Library/FlowNode/NodeModelBaseFunc.cs index db75423..20d873e 100644 --- a/Library/FlowNode/NodeModelBaseFunc.cs +++ b/Library/FlowNode/NodeModelBaseFunc.cs @@ -262,8 +262,9 @@ namespace Serein.Library catch (Exception ex) { newFlowData = null; - await Console.Out.WriteLineAsync($"节点[{this.MethodDetails?.MethodName}]异常:" + ex); + context.Env.WriteLine(InfoType.ERROR,$"节点[{this.Guid}]异常:" + ex); context.NextOrientation = ConnectionInvokeType.IsError; + context.ExceptionOfRuning = ex; } @@ -455,16 +456,31 @@ namespace Serein.Library } #endregion - #region 处理Get表达式 - if (pd.IsExplicitData // 输入了表达式 - && pd.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase) // Get表达式 - ) + #region 处理 @Get / @DTC 表达式 (Data type conversion) / @Data (全局数据) + if (pd.IsExplicitData) { - //var previousNode = context.GetPreviousNode(nodeModel); - //var previousFlowData = context.GetFlowData(previousNode.Guid); // 当前传递的数据 - // 执行表达式从上一节点获取对象 - inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, inputParameter, out _); + + // @Get 表达式 (从上一节点获取对象) + if (pd.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase)) + { + inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, inputParameter, out _); + } + + // @DTC 表达式 (Data type conversion) + if (pd.DataValue.StartsWith("@dtc", StringComparison.OrdinalIgnoreCase)) + { + inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, inputParameter, out _); + } + + // @Data 表达式 (获取全局数据) + if (pd.DataValue.StartsWith("@data", StringComparison.OrdinalIgnoreCase)) + { + inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, inputParameter, out _); + } + } + + #endregion #endregion diff --git a/Library/SereinBaseFunction.cs b/Library/SereinBaseFunction.cs index 420f2a0..0064df3 100644 --- a/Library/SereinBaseFunction.cs +++ b/Library/SereinBaseFunction.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; +using System.Text; namespace Serein.Library { @@ -88,21 +89,57 @@ namespace Serein.Library return value; } + [NodeAction(NodeType.Action, "文本拼接")] + private string SereinTextJoin(params object[] value) + { + StringBuilder sb = new StringBuilder(); + foreach (var item in value) + { + var tmp = item.ToString(); + if (tmp == "\\n") + { + sb.Append(Environment.NewLine); + } + else if (tmp == "\\t") + { + sb.Append('\t'); + } + else + { + sb.Append(tmp); + } + } + return sb.ToString(); + } - /* if (!DynamicObjectHelper.TryResolve(dict, className, out var result)) - { - Console.WriteLine("赋值过程中有错误,请检查属性名和类型!"); - } - else - { - DynamicObjectHelper.PrintObjectProperties(result); - } - //if (!ObjDynamicCreateHelper.TryResolve(externalData, "RootType", out var result)) - //{ - // Console.WriteLine("赋值过程中有错误,请检查属性名和类型!"); - //} - //ObjDynamicCreateHelper.PrintObjectProperties(result!); - return result;*/ + [NodeAction(NodeType.Action, "键值对动态构建对象")] + private object SereinKvDataToObject(Dictionary dict, + string classTypeName = "newClass_dynamic", + bool IsPrint = false) + { + if (!DynamicObjectHelper.TryResolve(dict, classTypeName, out var result)) + { + Console.WriteLine("赋值过程中有错误,请检查属性名和类型!"); + } + else + { + if (IsPrint) + { + Console.WriteLine("创建完成,正在打印结果"); + DynamicObjectHelper.PrintObjectProperties(result); + } + } + return result; + } + + + [NodeAction(NodeType.Action, "设置/更新全局数据")] + private object SereinAddOrUpdateFlowGlobalData(string name,object data) + { + SereinEnv.EnvGlobalData.AddOrUpdate(name, data,(k,o)=> data); + return data; + } + } } diff --git a/Library/Utils/ConvertHelper.cs b/Library/Utils/ConvertHelper.cs index e5b0184..5323bc4 100644 --- a/Library/Utils/ConvertHelper.cs +++ b/Library/Utils/ConvertHelper.cs @@ -201,6 +201,10 @@ namespace Serein.Library.Utils result = nuint.Parse(valueStr, CultureInfo.InvariantCulture); } #endif + else if(type == typeof(DateTime)) + { + return DateTime.Parse(valueStr); + } else { throw new ArgumentException("非预期值类型"); diff --git a/Library/Utils/SereinEnv.cs b/Library/Utils/SereinEnv.cs index 618ea0d..0051bb1 100644 --- a/Library/Utils/SereinEnv.cs +++ b/Library/Utils/SereinEnv.cs @@ -1,5 +1,6 @@ using Serein.Library.Api; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; @@ -11,6 +12,39 @@ namespace Serein.Library.Utils public static class SereinEnv { private static IFlowEnvironment environment; + + /// + /// 记录全局数据 + /// + public static ConcurrentDictionary EnvGlobalData { get; } = new ConcurrentDictionary(); + /// + /// 清空全局数据 + /// + public static void ClearGlobalData() + { + foreach (var nodeObj in EnvGlobalData.Values) + { + if (nodeObj != null) + { + if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable) + { + disposable?.Dispose(); + } + } + else + { + + } + } + EnvGlobalData.Clear(); + } + + + + /// + /// 设置运行流程 + /// + /// public static void SetEnv(IFlowEnvironment environment) { if (environment != null) @@ -18,10 +52,22 @@ namespace Serein.Library.Utils SereinEnv.environment = environment; } } - public static void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial) + + /// + /// 输出内容 + /// + /// 类型 + /// 内容 + /// 级别 + public static void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.General) { SereinEnv.environment.WriteLine(type,message,@class); } + + + + + } } diff --git a/Library/Utils/SereinExpression/SerinExpressionEvaluator.cs b/Library/Utils/SereinExpression/SerinExpressionEvaluator.cs index 591e01c..c3bbf02 100644 --- a/Library/Utils/SereinExpression/SerinExpressionEvaluator.cs +++ b/Library/Utils/SereinExpression/SerinExpressionEvaluator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; +using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -83,6 +84,16 @@ namespace Serein.Library.Utils.SereinExpression isChange = true; result = SetMember(targetObJ, operand); } + else if (operation == "@dtc") + { + isChange = true; + result = DataTypeConversion(targetObJ, operand); + } + else if (operation == "@data") + { + isChange = true; + result = GetGlobleData(targetObJ, operand); + } else { throw new NotSupportedException($"Operation {operation} is not supported."); @@ -402,11 +413,106 @@ namespace Serein.Library.Utils.SereinExpression { return ComputedNumber(value, expression); } - private static T ComputedNumber(object value, string expression) where T : struct, IComparable { T result = value.ToConvert(); return SerinArithmeticExpressionEvaluator.Evaluate(expression, result); } + + /// + /// 数据类型转换 + /// + /// + /// + /// + private static object DataTypeConversion(object value, string expression) + { + Type tempType; + + int typeStartIndex = expression.IndexOf('<'); + int typeEndIndex = expression.IndexOf('>'); + string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1) + .Trim().ToLower(); // 手动置顶的类型 + string valueStr = expression.Substring(typeEndIndex + 1, expression.Length - typeEndIndex - 1); + switch (typeStr) + { + case "bool": + tempType = typeof(bool); + break; + case "float": + tempType = typeof(float); + break; + case "decimal": + tempType = typeof(decimal); + break; + case "double": + tempType = typeof(double); + break; + case "sbyte": + tempType = typeof(sbyte); + break; + case "byte": + tempType = typeof(byte); + break; + case "short": + tempType = typeof(short); + break; + case "ushort": + tempType = typeof(ushort); + break; + case "int": + tempType = typeof(int); + break; + case "uint": + tempType = typeof(uint); + break; + case "long": + tempType = typeof(long); + break; + case "ulong": + tempType = typeof(ulong); + break; + // 如果需要支持 nint 和 nuint + // case "nint": + // tempType = typeof(nint); + // break; + // case "nuint": + // tempType = typeof(nuint); + // break; + case "string": + tempType = typeof(string); + break; + case "datetime": + tempType = typeof(DateTime); + break; + default: + tempType = Type.GetType(typeStr); + break; + } + + if (tempType.IsValueType) + { + return valueStr.ToValueData(tempType); + } + else + { + return null; + } + } + + + /// + /// 获取全局数据 + /// + /// + /// + /// + private static object GetGlobleData(object value, string expression) + { + var keyName = expression; + SereinEnv.EnvGlobalData.TryGetValue(keyName, out var data); + + return data; + } } } diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index c9b60c1..0145f36 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -323,8 +323,6 @@ namespace Serein.NodeFlow.Env /// private FlowStarter? flowStarter; - - #endregion #region 环境对外接口 @@ -526,6 +524,8 @@ namespace Serein.NodeFlow.Env } + + /// /// 加载项目文件 /// @@ -535,13 +535,15 @@ namespace Serein.NodeFlow.Env { var projectData = flowEnvInfo.Project; // 加载项目配置文件 - var dllPaths = projectData.Librarys.Select(it => it.FileName).ToList(); + var dllPaths = projectData.Librarys.Select(it => it.FilePath).ToList(); List methodDetailss = []; // 遍历依赖项中的特性注解,生成方法详情 foreach (var dllPath in dllPaths) { - var dllFilePath = Path.GetFullPath(Path.Combine(filePath, dllPath)); + string cleanedRelativePath = dllPath.TrimStart('.', '\\'); + var tmpPath = Path.Combine(filePath, cleanedRelativePath); + var dllFilePath = Path.GetFullPath(tmpPath); LoadLibrary(dllFilePath); // 加载项目文件时加载对应的程序集 } @@ -550,39 +552,48 @@ namespace Serein.NodeFlow.Env // 加载节点 foreach (NodeInfo? nodeInfo in projectData.Nodes) { - var controlType = FlowFunc.GetNodeControlType(nodeInfo); + NodeControlType controlType = FlowFunc.GetNodeControlType(nodeInfo); if (controlType == NodeControlType.None) { continue; } + MethodDetails? methodDetails = null; + + if (controlType.IsBaseNode()) + { + // 加载基础节点 + methodDetails = new MethodDetails(); + } else { + // 加载方法节点 if (string.IsNullOrEmpty(nodeInfo.AssemblyName) && string.IsNullOrEmpty(nodeInfo.MethodName)) { continue; } - MethodDetails? methodDetails = null; - FlowLibraryManagement.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName,out methodDetails); // 加载项目时尝试获取方法信息 - var nodeModel = FlowFunc.CreateNode(this, controlType, methodDetails); // 加载项目时创建节点 - nodeModel.LoadInfo(nodeInfo); // 创建节点model - if (nodeModel is null) - { - nodeInfo.Guid = string.Empty; - continue; - } - - TryAddNode(nodeModel); // 加载项目时将节点加载到环境中 - if (nodeInfo.ChildNodeGuids?.Length > 0) - { - regionChildNodes.Add((nodeModel, nodeInfo.ChildNodeGuids)); - - UIContextOperation?.Invoke(() => OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position))); - } - else - { - ordinaryNodes.Add((nodeModel, nodeInfo.Position)); - } + FlowLibraryManagement.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName, out methodDetails); // 加载项目时尝试获取方法信息 } + + var nodeModel = FlowFunc.CreateNode(this, controlType, methodDetails); // 加载项目时创建节点 + nodeModel.LoadInfo(nodeInfo); // 创建节点model + if (nodeModel is null) + { + nodeInfo.Guid = string.Empty; + continue; + } + + TryAddNode(nodeModel); // 加载项目时将节点加载到环境中 + if (nodeInfo.ChildNodeGuids?.Length > 0) + { + regionChildNodes.Add((nodeModel, nodeInfo.ChildNodeGuids)); + + UIContextOperation?.Invoke(() => OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position))); + } + else + { + ordinaryNodes.Add((nodeModel, nodeInfo.Position)); + } + } // 加载区域子项 foreach ((NodeModelBase region, string[] childNodeGuids) item in regionChildNodes) @@ -1323,7 +1334,6 @@ namespace Serein.NodeFlow.Env return result; } - /// /// 记录节点更改数据,防止重复更改 /// @@ -1466,6 +1476,31 @@ namespace Serein.NodeFlow.Env #region 流程依赖类库的接口 + + /// + /// 添加或更新全局数据 + /// + /// 数据名称 + /// 数据集 + /// + public object AddOrUpdateGlobalData(string keyName, object data) + { + SereinEnv.EnvGlobalData.AddOrUpdate(keyName, data, (k, o) => data); + return data; + } + + /// + /// 获取全局数据 + /// + /// 数据名称 + /// + public object? GetGlobalData(string keyName) + { + SereinEnv.EnvGlobalData.TryGetValue(keyName, out var data); + return data; + } + + /// /// 运行时加载 /// diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs index 37d11e1..704f607 100644 --- a/NodeFlow/Env/FlowEnvironmentDecorator.cs +++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs @@ -455,6 +455,27 @@ namespace Serein.NodeFlow.Env } #region 流程依赖类库的接口 + /// + /// 添加或更新全局数据 + /// + /// 数据名称 + /// 数据集 + /// + public object AddOrUpdateGlobalData(string keyName, object data) + { + return currentFlowEnvironment.AddOrUpdateGlobalData(keyName, data); + } + + /// + /// 获取全局数据 + /// + /// 数据名称 + /// + public object GetGlobalData(string keyName) + { + return currentFlowEnvironment.GetGlobalData(keyName); + } + /// /// 运行时加载 @@ -574,6 +595,8 @@ namespace Serein.NodeFlow.Env return IOC.Run(action); } + + #endregion diff --git a/NodeFlow/Env/FlowFunc.cs b/NodeFlow/Env/FlowFunc.cs index e7ec836..3f4f92c 100644 --- a/NodeFlow/Env/FlowFunc.cs +++ b/NodeFlow/Env/FlowFunc.cs @@ -10,7 +10,19 @@ namespace Serein.NodeFlow.Env /// public static class FlowFunc { - + /// + /// 判断是否为基础节点 + /// + /// + public static bool IsBaseNode(this NodeControlType nodeControlType) + { + if(nodeControlType == NodeControlType.ExpCondition + || nodeControlType == NodeControlType.ExpOp) + { + return true; + } + return false; + } /// /// 创建节点 diff --git a/NodeFlow/Env/RemoteFlowEnvironment.cs b/NodeFlow/Env/RemoteFlowEnvironment.cs index 522a257..4cf6dd4 100644 --- a/NodeFlow/Env/RemoteFlowEnvironment.cs +++ b/NodeFlow/Env/RemoteFlowEnvironment.cs @@ -895,6 +895,31 @@ namespace Serein.NodeFlow.Env this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:LoadAllNativeLibraryOfRuning"); } + + + /// + /// 添加或更新全局数据 + /// + /// 数据名称 + /// 数据集 + /// + public object AddOrUpdateGlobalData(string keyName, object data) + { + this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:AddOrUpdateGlobalData"); + return null; + } + /// + /// 获取全局数据 + /// + /// 数据名称 + /// + public object GetGlobalData(string keyName) + { + this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:GetGlobalData"); + return null; + } + + #endregion } } diff --git a/NodeFlow/FlowStarter.cs b/NodeFlow/FlowStarter.cs index 659df3d..f85fede 100644 --- a/NodeFlow/FlowStarter.cs +++ b/NodeFlow/FlowStarter.cs @@ -241,13 +241,9 @@ namespace Serein.NodeFlow _flipFlopCts?.Dispose(); } // 通知所有流程上下文停止运行 TerminateAllGlobalFlipflop(); // 确保所有触发器不再运行 - - + SereinEnv.ClearGlobalData(); // 清空全局数据缓存 NativeDllHelper.FreeLibrarys(); // 卸载所有已加载的 Native Dll - //NativeDllHelper.FreeLibrarys(); // 卸载所有已加载的 Native Dll - - env.FlowState = RunState.Completion; env.FlipFlopState = RunState.Completion; @@ -395,7 +391,7 @@ namespace Serein.NodeFlow } catch (FlipflopException ex) { - await Console.Out.WriteLineAsync($"触发器[{singleFlipFlopNode.MethodDetails.MethodName}]因非预期异常终止。"+ex.Message); + env.WriteLine(InfoType.ERROR,$"触发器[{singleFlipFlopNode.MethodDetails.MethodName}]因非预期异常终止。"+ex.Message); if (ex.Type == FlipflopException.CancelClass.CancelFlow) { break; @@ -403,7 +399,8 @@ namespace Serein.NodeFlow } catch (Exception ex) { - await Console.Out.WriteLineAsync(ex.Message); + env.WriteLine(InfoType.ERROR, $"触发器[{singleFlipFlopNode.Guid}]异常。"+ ex.Message); + //await Console.Out.WriteLineAsync(ex.Message); } finally { diff --git a/NodeFlow/Model/SingleGlobalDataNode.cs b/NodeFlow/Model/SingleGlobalDataNode.cs new file mode 100644 index 0000000..86ee5da --- /dev/null +++ b/NodeFlow/Model/SingleGlobalDataNode.cs @@ -0,0 +1,30 @@ +using Serein.Library; +using Serein.Library.Api; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Model +{ + /// + /// 全局数据节点 + /// + public class SingleGlobalDataNode : NodeModelBase + { + public SingleGlobalDataNode(IFlowEnvironment environment) : base(environment) + { + } + + public override ParameterData[] GetParameterdatas() + { + throw new NotImplementedException(); + } + + public override void OnCreating() + { + throw new NotImplementedException(); + } + } +} diff --git a/NodeFlow/Tool/FlowLibraryManagement.cs b/NodeFlow/Tool/FlowLibraryManagement.cs index c42e13d..07234ac 100644 --- a/NodeFlow/Tool/FlowLibraryManagement.cs +++ b/NodeFlow/Tool/FlowLibraryManagement.cs @@ -206,10 +206,8 @@ namespace Serein.NodeFlow.Tool private (NodeLibraryInfo, List) LoadDllNodeInfo(string dllFilePath) { var fileName = Path.GetFileName(dllFilePath); // 获取文件名 - if (SereinLibraryDll.Equals(fileName)) { - return LoadAssembly(typeof(IFlowEnvironment).Assembly, () => { //SereinEnv.PrintInfo(InfoType.WRAN, "基础模块不能卸载"); }); diff --git a/WorkBench/App.xaml.cs b/WorkBench/App.xaml.cs index 5e8e555..a11be47 100644 --- a/WorkBench/App.xaml.cs +++ b/WorkBench/App.xaml.cs @@ -15,13 +15,14 @@ namespace Serein.Workbench { #if DEBUG - if (1 == 1) + if (1 == 0 ) { string filePath; filePath = @"F:\临时\project\linux\project.dnf"; filePath = @"F:\临时\project\linux\http\project.dnf"; filePath = @"F:\临时\project\yolo flow\project.dnf"; filePath = @"F:\临时\project\data\project.dnf"; + filePath = @"C:\Users\Az\source\repos\CLBanyunqiState\CLBanyunqiState\bin\Release\net8.0\PLCproject.dnf"; string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容 App.FlowProjectData = JsonConvert.DeserializeObject(content); App.FileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;// diff --git a/WorkBench/MainWindow.xaml.cs b/WorkBench/MainWindow.xaml.cs index bbf5cdc..f30f431 100644 --- a/WorkBench/MainWindow.xaml.cs +++ b/WorkBench/MainWindow.xaml.cs @@ -578,7 +578,7 @@ namespace Serein.Workbench NodeControlType.Action => CreateNodeControl(nodeModelBase), //typeof(ActionNodeControl), NodeControlType.Flipflop => CreateNodeControl(nodeModelBase), NodeControlType.ExpCondition => CreateNodeControl(nodeModelBase), - NodeControlType.ExpOp => CreateNodeControl(nodeModelBase), + NodeControlType.ExpOp => CreateNodeControl(nodeModelBase), NodeControlType.ConditionRegion => CreateNodeControl(nodeModelBase), _ => null, }; @@ -2504,7 +2504,7 @@ namespace Serein.Workbench NodeLibraryInfo? library = projectData.Librarys[index]; try { - string targetPath = System.IO.Path.Combine(librarySavePath, library.FileName); // 目标文件夹 + string targetPath = System.IO.Path.Combine(librarySavePath, library.FilePath); // 目标文件夹 #if WINDOWS string sourceFile = library.FilePath; // 源文件夹 #else diff --git a/WorkBench/Node/View/ActionNodeControl.xaml b/WorkBench/Node/View/ActionNodeControl.xaml index 7baaddf..7d3064d 100644 --- a/WorkBench/Node/View/ActionNodeControl.xaml +++ b/WorkBench/Node/View/ActionNodeControl.xaml @@ -15,8 +15,10 @@ + + @@ -24,7 +26,10 @@ - + + + + - + + + + + diff --git a/WorkBench/Node/View/ActionNodeControl.xaml.cs b/WorkBench/Node/View/ActionNodeControl.xaml.cs index bcd3500..8619d87 100644 --- a/WorkBench/Node/View/ActionNodeControl.xaml.cs +++ b/WorkBench/Node/View/ActionNodeControl.xaml.cs @@ -16,7 +16,11 @@ namespace Serein.Workbench.Node.View { DataContext = viewModel; InitializeComponent(); + if(ExecuteJunctionControl.MyNode != null) + { + ExecuteJunctionControl.MyNode.Guid = viewModel.NodeModel.Guid; + } } /// diff --git a/WorkBench/Node/View/ConditionNodeControl.xaml.cs b/WorkBench/Node/View/ConditionNodeControl.xaml.cs index ed72782..a228615 100644 --- a/WorkBench/Node/View/ConditionNodeControl.xaml.cs +++ b/WorkBench/Node/View/ConditionNodeControl.xaml.cs @@ -21,6 +21,7 @@ namespace Serein.Workbench.Node.View DataContext = viewModel; InitializeComponent(); } + /// /// 入参控制点(可能有,可能没) /// diff --git a/WorkBench/Node/View/ConditionRegionControl.xaml.cs b/WorkBench/Node/View/ConditionRegionControl.xaml.cs index d31c69b..637b3b4 100644 --- a/WorkBench/Node/View/ConditionRegionControl.xaml.cs +++ b/WorkBench/Node/View/ConditionRegionControl.xaml.cs @@ -26,8 +26,6 @@ namespace Serein.Workbench.Node.View - - /// /// 添加条件控件 /// diff --git a/WorkBench/Node/View/ExpOpNodeControl.xaml.cs b/WorkBench/Node/View/ExpOpNodeControl.xaml.cs index 7525618..6b0f814 100644 --- a/WorkBench/Node/View/ExpOpNodeControl.xaml.cs +++ b/WorkBench/Node/View/ExpOpNodeControl.xaml.cs @@ -11,11 +11,11 @@ namespace Serein.Workbench.Node.View public ExpOpNodeControl() : base() { // 窗体初始化需要 - ViewModel = new ExpOpNodeViewModel(new SingleExpOpNode(null)); + ViewModel = new ExpOpNodeControlViewModel(new SingleExpOpNode(null)); DataContext = ViewModel; InitializeComponent(); } - public ExpOpNodeControl(ExpOpNodeViewModel viewModel) :base(viewModel) + public ExpOpNodeControl(ExpOpNodeControlViewModel viewModel) :base(viewModel) { DataContext = viewModel; InitializeComponent(); diff --git a/WorkBench/Serein.WorkBench.csproj b/WorkBench/Serein.WorkBench.csproj index 6bef458..5b4501c 100644 --- a/WorkBench/Serein.WorkBench.csproj +++ b/WorkBench/Serein.WorkBench.csproj @@ -55,6 +55,11 @@ + + + diff --git a/WorkBench/Themes/MethodDetailsControl.xaml b/WorkBench/Themes/MethodDetailsControl.xaml index de53695..a2c9bb5 100644 --- a/WorkBench/Themes/MethodDetailsControl.xaml +++ b/WorkBench/Themes/MethodDetailsControl.xaml @@ -46,6 +46,7 @@ Visibility="{Binding IsParams, Mode=OneWay, Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}" /> +