From 561b6d764f48f5756d697915be4b779301c5f432 Mon Sep 17 00:00:00 2001 From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com> Date: Mon, 28 Oct 2024 15:21:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/Api/IFlowEnvironment.cs | 7 +- Library/FlowNode/MethodDetails.cs | 35 ++++++--- Library/FlowNode/MethodDetailsInfo.cs | 2 +- Library/FlowNode/NodeDebugSetting.cs | 17 ++-- Library/FlowNode/NodeModelBaseData.cs | 1 - Library/FlowNode/NodeModelBaseFunc.cs | 2 +- Library/FlowNode/ParameterDetails.cs | 15 +++- .../WebSocket/Handle/WebSocketHandleModule.cs | 5 +- .../WebSocket/Handle/WebSocketMsgContext.cs | 11 ++- .../Handle/WebSocketMsgHandleHelper.cs | 9 ++- Library/Network/WebSocket/TestExtension.cs | 62 ++++++++++----- Library/Network/WebSocket/WebSocketClient.cs | 21 ++--- Library/Network/WebSocket/WebSocketServer.cs | 25 +++--- Library/NodeAttribute.cs | 4 +- NodeFlow/Env/FlowEnvironment.cs | 77 ++++++++++++------- NodeFlow/Env/FlowEnvironmentDecorator.cs | 17 +++- NodeFlow/Env/FlowFunc.cs | 2 +- NodeFlow/Env/MsgControllerOfServer.cs | 3 + NodeFlow/Env/RemoteFlowEnvironment.cs | 29 ++++--- NodeFlow/Model/CompositeConditionNode.cs | 2 +- NodeFlow/Tool/NodeMethodDetailsHelper.cs | 8 +- .../ParameterDetailsPropertyGenerator.cs | 34 +++++--- WorkBench/MainWindow.xaml | 17 ++-- WorkBench/MainWindow.xaml.cs | 35 ++++++--- WorkBench/Node/View/ActionNodeControl.xaml | 4 +- WorkBench/Node/View/DllControlControl.xaml.cs | 6 +- WorkBench/Node/View/FlipflopNodeControl.xaml | 4 +- .../Themes/NodeTreeItemViewControl.xaml.cs | 6 +- 28 files changed, 295 insertions(+), 165 deletions(-) diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index 64017da..5b50ab8 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -517,13 +517,12 @@ namespace Serein.Library.Api /// 表示是否正在控制远程 /// Local control remote env /// - bool IsLcR { get; } + bool IsControlRemoteEnv { get; } /// - /// 表示是否受到远程控制 - /// Remote control local env + /// 是否运行在控制台上 /// - bool IsRcL { get; } + // bool IsRuningOnConsole { get; } /// /// 流程运行状态 diff --git a/Library/FlowNode/MethodDetails.cs b/Library/FlowNode/MethodDetails.cs index a329bcc..67b26e4 100644 --- a/Library/FlowNode/MethodDetails.cs +++ b/Library/FlowNode/MethodDetails.cs @@ -2,6 +2,7 @@ using Serein.Library.Utils; using System; using System.Linq; +using System.Text; namespace Serein.Library { @@ -12,7 +13,7 @@ namespace Serein.Library [NodeProperty(ValuePath = NodeValuePath.Method)] public partial class MethodDetails { - private readonly IFlowEnvironment env; + // private readonly IFlowEnvironment env; /// /// 对应的节点 @@ -58,10 +59,10 @@ namespace Serein.Library /// - /// 方法说明 + /// 方法别名 /// [PropertyInfo] - private string _methodTips; + private string _methodAnotherName; /// @@ -109,7 +110,7 @@ namespace Serein.Library throw new ArgumentException("无效的节点类型"); } MethodName = Info.MethodName; - MethodTips = Info.MethodTips; + MethodAnotherName = Info.MethodAnotherName; MethodDynamicType = nodeType; ReturnType = Type.GetType(Info.ReturnTypeFullName); ParameterDetailss = Info.ParameterDetailsInfos.Select(pinfo => new ParameterDetails(pinfo)).ToArray(); @@ -121,10 +122,12 @@ namespace Serein.Library /// public MethodDetailsInfo ToInfo() { + + return new MethodDetailsInfo { MethodName = MethodName, - MethodTips = MethodTips, + MethodAnotherName = MethodAnotherName, NodeType = MethodDynamicType.ToString(), ParameterDetailsInfos = ParameterDetailss.Select(p => p.ToInfo()).ToArray(), ReturnTypeFullName = ReturnType.FullName, @@ -142,7 +145,7 @@ namespace Serein.Library ActingInstance = this.ActingInstance, ActingInstanceType = this.ActingInstanceType, MethodDynamicType = this.MethodDynamicType, - MethodTips = this.MethodTips, + MethodAnotherName = this.MethodAnotherName, ReturnType = this.ReturnType, MethodName = this.MethodName, MethodLockName = this.MethodLockName, @@ -152,9 +155,23 @@ namespace Serein.Library return md; } - - - + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"方法别名:{this.MethodAnotherName}"); + sb.AppendLine($"方法名称:{this.MethodName}"); + sb.AppendLine($"需要实例:{this.ActingInstanceType.FullName}"); + sb.AppendLine($""); + sb.AppendLine($"入参参数信息:"); + foreach (var arg in this.ParameterDetailss) + { + sb.AppendLine($" {arg.ToString()}"); + } + sb.AppendLine($""); + sb.AppendLine($"返回值信息:"); + sb.AppendLine($" {this.ReturnType.FullName}"); + return sb.ToString(); + } ///// ///// 每个节点有独自的MethodDetails实例 diff --git a/Library/FlowNode/MethodDetailsInfo.cs b/Library/FlowNode/MethodDetailsInfo.cs index c7a228a..8e0383f 100644 --- a/Library/FlowNode/MethodDetailsInfo.cs +++ b/Library/FlowNode/MethodDetailsInfo.cs @@ -29,7 +29,7 @@ namespace Serein.Library /// /// 方法说明 /// - public string MethodTips { get; set; } + public string MethodAnotherName { get; set; } /// /// 参数内容 diff --git a/Library/FlowNode/NodeDebugSetting.cs b/Library/FlowNode/NodeDebugSetting.cs index 2395651..b3e7cac 100644 --- a/Library/FlowNode/NodeDebugSetting.cs +++ b/Library/FlowNode/NodeDebugSetting.cs @@ -12,12 +12,6 @@ namespace Serein.Library [NodeProperty(ValuePath = NodeValuePath.DebugSetting)] public partial class NodeDebugSetting { - /// - /// 对应的节点 - /// - [PropertyInfo(IsProtection = true)] - private NodeModelBase _nodeModel; - /// /// 创建属于某个节点的调试设置 /// @@ -26,6 +20,13 @@ namespace Serein.Library { NodeModel = nodeModel; } + + /// + /// 对应的节点 + /// + [PropertyInfo(IsProtection = true)] + private NodeModelBase _nodeModel; + /// /// 是否使能 /// @@ -41,11 +42,9 @@ namespace Serein.Library /// /// 中断级别,暂时停止继续执行后继分支。 /// - [PropertyInfo(IsNotification = true, CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);")] + [PropertyInfo(IsNotification = true)] // CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);" private bool _isInterrupt = false; - //private const string MyInteruptCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);"; // 添加到中断的自定义代码 - /// /// 取消中断的回调函数 /// diff --git a/Library/FlowNode/NodeModelBaseData.cs b/Library/FlowNode/NodeModelBaseData.cs index 7d51e8e..545e89b 100644 --- a/Library/FlowNode/NodeModelBaseData.cs +++ b/Library/FlowNode/NodeModelBaseData.cs @@ -81,7 +81,6 @@ namespace Serein.Library [PropertyInfo] private Exception _runingException ; - } diff --git a/Library/FlowNode/NodeModelBaseFunc.cs b/Library/FlowNode/NodeModelBaseFunc.cs index f743537..32facce 100644 --- a/Library/FlowNode/NodeModelBaseFunc.cs +++ b/Library/FlowNode/NodeModelBaseFunc.cs @@ -53,7 +53,7 @@ namespace Serein.Library { Guid = Guid, MethodName = MethodDetails?.MethodName, - Label = DisplayName ?? "", + Label = MethodDetails?.MethodAnotherName, Type = this.GetType().ToString(), TrueNodes = trueNodes.ToArray(), FalseNodes = falseNodes.ToArray(), diff --git a/Library/FlowNode/ParameterDetails.cs b/Library/FlowNode/ParameterDetails.cs index 683edc5..30fa744 100644 --- a/Library/FlowNode/ParameterDetails.cs +++ b/Library/FlowNode/ParameterDetails.cs @@ -68,7 +68,6 @@ namespace Serein.Library [PropertyInfo] private string _argDataSourceNodeGuid; - /// /// 方法入参需要的类型。 /// @@ -128,7 +127,6 @@ namespace Serein.Library ExplicitType = Type.GetType(info.ExplicitTypeFullName); ExplicitTypeName = info.ExplicitTypeName; Items = info.Items; - } /// @@ -171,6 +169,19 @@ namespace Serein.Library }; return pd; } + + public override string ToString() + { + if(_convertor is null) + { + return $"[{this.Index}] {this.Name} : {this.DataType.FullName}"; + } + else + { + + } + return $"[{this.Index}] {this.Name} : {this.ExplicitType.FullName} -> {this.DataType.FullName}"; + } } diff --git a/Library/Network/WebSocket/Handle/WebSocketHandleModule.cs b/Library/Network/WebSocket/Handle/WebSocketHandleModule.cs index d374f16..acfd58d 100644 --- a/Library/Network/WebSocket/Handle/WebSocketHandleModule.cs +++ b/Library/Network/WebSocket/Handle/WebSocketHandleModule.cs @@ -123,7 +123,10 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle catch (Exception ex) { Console.WriteLine($"error in ws : {ex.Message}{Environment.NewLine}json value:{jsonObject}"); - return; + } + finally + { + context.Handle = true; } } diff --git a/Library/Network/WebSocket/Handle/WebSocketMsgContext.cs b/Library/Network/WebSocket/Handle/WebSocketMsgContext.cs index bdc7101..acbd5a4 100644 --- a/Library/Network/WebSocket/Handle/WebSocketMsgContext.cs +++ b/Library/Network/WebSocket/Handle/WebSocketMsgContext.cs @@ -11,7 +11,7 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle /// /// 消息处理上下文 /// - public class WebSocketMsgContext : IDisposable + public class WebSocketMsgContext /*: IDisposable*/ { public WebSocketMsgContext(Func sendAsync) { @@ -31,7 +31,14 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle /// /// 标记是否已经处理,如果是,则提前退出 /// - public bool Handle { get; set; } + public bool Handle { get => _handle; set{ + if(value) + { + Dispose(); + _handle = value; + } + } } + public bool _handle = false; /// /// 消息本体(JObject) diff --git a/Library/Network/WebSocket/Handle/WebSocketMsgHandleHelper.cs b/Library/Network/WebSocket/Handle/WebSocketMsgHandleHelper.cs index c957de4..c54c379 100644 --- a/Library/Network/WebSocket/Handle/WebSocketMsgHandleHelper.cs +++ b/Library/Network/WebSocket/Handle/WebSocketMsgHandleHelper.cs @@ -201,13 +201,18 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle /// /// 此次请求的上下文 /// - public async Task HandleAsync(WebSocketMsgContext context) + public void Handle(WebSocketMsgContext context) { foreach (var module in MyHandleModuleDict.Values) { - await module.HandleAsync(context); + if (context.Handle) + { + return; + } + _ = module.HandleAsync(context); } + } diff --git a/Library/Network/WebSocket/TestExtension.cs b/Library/Network/WebSocket/TestExtension.cs index 02acb67..1434b48 100644 --- a/Library/Network/WebSocket/TestExtension.cs +++ b/Library/Network/WebSocket/TestExtension.cs @@ -11,23 +11,25 @@ using System.Threading.Tasks; namespace Serein.Library.Network.WebSocketCommunication { - public class MsgQueueUtil + /// + /// 消息处理工具 + /// + public class MsgHandleUtil { - public ConcurrentQueue Msgs = new ConcurrentQueue(); - private readonly Channel _msgChannel; - public MsgQueueUtil() - { - _msgChannel = CreateChannel(); - } - private Channel CreateChannel() + /// + /// 初始化优先容器 + /// + /// + public MsgHandleUtil(int capacity = 100) { - return Channel.CreateBounded(new BoundedChannelOptions(100) + _msgChannel = Channel.CreateBounded(new BoundedChannelOptions(capacity) { FullMode = BoundedChannelFullMode.Wait }); } + /// /// 等待消息 @@ -35,27 +37,45 @@ namespace Serein.Library.Network.WebSocketCommunication /// public async Task WaitMsgAsync() { - var state = await _msgChannel.Reader.ReadAsync(); - return state; - } - - public void WriteMsg(string msg) - { - //Msgs.Enqueue(msg); - Console.WriteLine($"{DateTime.Now}{msg}{Environment.NewLine}"); - _ = _msgChannel.Writer.WriteAsync(msg); + // 检查是否可以读取消息 + if (await _msgChannel.Reader.WaitToReadAsync()) + { + return await _msgChannel.Reader.ReadAsync(); + } + return null; // 若通道关闭,则返回null } - public bool TryGetMsg(out string msg) + /// + /// 写入消息 + /// + /// 消息内容 + /// 是否写入成功 + public async Task WriteMsgAsync(string msg) { - return Msgs.TryDequeue(out msg); + try + { + await _msgChannel.Writer.WriteAsync(msg); + return true; + } + catch (ChannelClosedException) + { + // Channel 已关闭 + return false; + } } - + /// + /// 尝试关闭通道,停止写入消息 + /// + public void CloseChannel() + { + _msgChannel.Writer.Complete(); + } } + public class SocketExtension { /// diff --git a/Library/Network/WebSocket/WebSocketClient.cs b/Library/Network/WebSocket/WebSocketClient.cs index 94234be..8d0c22e 100644 --- a/Library/Network/WebSocket/WebSocketClient.cs +++ b/Library/Network/WebSocket/WebSocketClient.cs @@ -76,7 +76,7 @@ namespace Serein.Library.Network.WebSocketCommunication private async Task ReceiveAsync() { - var msgQueueUtil = new MsgQueueUtil(); + var msgQueueUtil = new MsgHandleUtil(); _ = Task.Run(async () => { await HandleMsgAsync(_client, msgQueueUtil); @@ -102,7 +102,7 @@ namespace Serein.Library.Network.WebSocketCommunication } while (!result.EndOfMessage); // 判断是否已经收到完整消息 var message = receivedMessage.ToString(); - msgQueueUtil.WriteMsg(message); + await msgQueueUtil.WriteMsgAsync(message); receivedMessage.Clear(); // 清空 StringBuilder 为下一条消息做准备 // 处理收到的完整消息 if (result.MessageType == WebSocketMessageType.Close) @@ -126,8 +126,7 @@ namespace Serein.Library.Network.WebSocketCommunication } - public async Task HandleMsgAsync(WebSocket webSocket, - MsgQueueUtil msgQueueUtil) + public async Task HandleMsgAsync(WebSocket webSocket, MsgHandleUtil msgQueueUtil) { async Task sendasync(string text) { @@ -136,11 +135,15 @@ namespace Serein.Library.Network.WebSocketCommunication while (true) { var message = await msgQueueUtil.WaitMsgAsync(); // 有消息时通知 - using (var context = new WebSocketMsgContext(sendasync)) - { - context.JsonObject = JObject.Parse(message); - await MsgHandleHelper.HandleAsync(context); // 处理消息 - } + var context = new WebSocketMsgContext(sendasync); + context.JsonObject = JObject.Parse(message); + MsgHandleHelper.Handle(context); // 处理消息 + + //using (var context = new WebSocketMsgContext(sendasync)) + //{ + // context.JsonObject = JObject.Parse(message); + // await MsgHandleHelper.HandleAsync(context); // 处理消息 + //} //_ = Task.Run(() => { // JObject json = JObject.Parse(message); diff --git a/Library/Network/WebSocket/WebSocketServer.cs b/Library/Network/WebSocket/WebSocketServer.cs index 240727f..dca9ee3 100644 --- a/Library/Network/WebSocket/WebSocketServer.cs +++ b/Library/Network/WebSocket/WebSocketServer.cs @@ -180,7 +180,7 @@ namespace Serein.Library.Network.WebSocketCommunication return; } - var msgQueueUtil = new MsgQueueUtil(); + var msgQueueUtil = new MsgHandleUtil(); _ = Task.Run(async () => { await HandleMsgAsync(webSocket,msgQueueUtil, authorizedHelper); @@ -219,7 +219,7 @@ namespace Serein.Library.Network.WebSocketCommunication // 完整消息已经接收到,准备处理 var message = receivedMessage.ToString(); // 获取消息文本 receivedMessage.Clear(); // 清空 StringBuilder 为下一条消息做准备 - msgQueueUtil.WriteMsg(message); // 处理消息 + await msgQueueUtil.WriteMsgAsync(message); // 处理消息 } catch (Exception ex) { @@ -231,7 +231,7 @@ namespace Serein.Library.Network.WebSocketCommunication public async Task HandleMsgAsync(WebSocket webSocket, - MsgQueueUtil msgQueueUtil, + MsgHandleUtil msgQueueUtil, WebSocketAuthorizedHelper authorizedHelper) { async Task sendasync(string text) @@ -254,18 +254,21 @@ namespace Serein.Library.Network.WebSocketCommunication return; } } + var context = new WebSocketMsgContext(sendasync); + context.JsonObject = JObject.Parse(message); + MsgHandleHelper.Handle(context); // 处理消息 - using (var context = new WebSocketMsgContext(sendasync)) - { - context.JsonObject = JObject.Parse(message); - await MsgHandleHelper.HandleAsync(context); // 处理消息 - } + //using (var context = new WebSocketMsgContext(sendasync)) + //{ + // context.JsonObject = JObject.Parse(message); + // await MsgHandleHelper.Handle(context); // 处理消息 + //} //_ = Task.Run(() => { - - - //}); + //}); + + } } diff --git a/Library/NodeAttribute.cs b/Library/NodeAttribute.cs index 750308a..8101672 100644 --- a/Library/NodeAttribute.cs +++ b/Library/NodeAttribute.cs @@ -91,7 +91,7 @@ namespace Serein.Library { Scan = scan; MethodDynamicType = methodDynamicType; - MethodTips = methodTips; + AnotherName = methodTips; LockName = lockName; } /// @@ -101,7 +101,7 @@ namespace Serein.Library /// /// 类似于注释的效果 /// - public string MethodTips; + public string AnotherName; /// /// 标记节点行为 /// diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index 4037dba..618b6b5 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -63,13 +63,7 @@ namespace Serein.NodeFlow.Env /// 表示是否正在控制远程 /// Local control remote env /// - public bool IsLcR { get; set; } - /// - /// 表示是否受到远程控制 - /// Remote control local env - /// - public bool IsRcL { get; set; } - + public bool IsControlRemoteEnv { get; set; } /// @@ -81,6 +75,7 @@ namespace Serein.NodeFlow.Env if (clientMsgManage is null) { clientMsgManage = new MsgControllerOfServer(this); + //clientMsgManage = new MsgControllerOfServer(this,"123456"); } _ = clientMsgManage.StartRemoteServerAsync(port); } @@ -657,7 +652,7 @@ namespace Serein.NodeFlow.Env && NodeModels.TryGetValue(pd.ArgDataSourceNodeGuid, out var fromNode)) { - ConnectGerResultOfNode(fromNode, toNode, pd.ArgDataSourceType, pd.Index); + await ConnectArgSourceOfNodeAsync(fromNode, toNode, pd.ArgDataSourceType, pd.Index); } } } @@ -678,7 +673,7 @@ namespace Serein.NodeFlow.Env /// 密码 public async Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token) { - if (IsLcR) + if (IsControlRemoteEnv) { await Console.Out.WriteLineAsync($"当前已经连接远程环境"); return (false, null); @@ -702,7 +697,7 @@ namespace Serein.NodeFlow.Env return (false, null); } await Console.Out.WriteLineAsync("连接成功,开始验证Token"); - IsLcR = true; + IsControlRemoteEnv = true; return (true, remoteMsgUtil); } @@ -711,7 +706,7 @@ namespace Serein.NodeFlow.Env /// public void ExitRemoteEnv() { - IsLcR = false; + IsControlRemoteEnv = false; } /// @@ -916,7 +911,7 @@ namespace Serein.NodeFlow.Env var fromNode = GuidToModel(fromNodeGuid); var toNode = GuidToModel(toNodeGuid); if (fromNode is null || toNode is null) return false; - (var type,var state) = CheckConnect(fromNode, toNode, fromNodeJunctionType, toNodeJunctionType); + (var type, var state) = CheckConnect(fromNode, toNode, fromNodeJunctionType, toNodeJunctionType); if (!state) { Console.WriteLine("出现非预期的连接行为"); @@ -977,7 +972,7 @@ namespace Serein.NodeFlow.Env } // 确定方法入参关系 - state = ConnectGerResultOfNode(fromNode, toNode, connectionArgSourceType, argIndex); // 本地环境进行连接 + state = await ConnectArgSourceOfNodeAsync(fromNode, toNode, connectionArgSourceType, argIndex); // 本地环境进行连接 } return state; @@ -1291,21 +1286,36 @@ namespace Serein.NodeFlow.Env { var nodeModel = GuidToModel(nodeGuid); if (nodeModel is null) return; - if (NodeValueChangeLogger.Remove((nodeGuid, path, value))) - { - // 说明存在过重复的修改 - return; - } - NodeValueChangeLogger.Add((nodeGuid, path, value)); - var setExp = $"@Set .{path} = {value}"; // 生成 set 表达式 - //var getExp = $"@Get .{path}"; - SerinExpressionEvaluator.Evaluate(setExp, nodeModel, out _); // 更改对应的数据 - //var getResult = SerinExpressionEvaluator.Evaluate(getExp, nodeModel, out _); - //Console.WriteLine($"Set表达式:{setExp},result : {getResult}"); - + SerinExpressionEvaluator.Evaluate($"@Set .{path} = {value}", nodeModel, out _); // 更改对应的数据 + + //if (NodeValueChangeLogger.Remove((nodeGuid, path, value))) + //{ + // // 说明存在过重复的修改 + // return; + //} + //NodeValueChangeLogger.Add((nodeGuid, path, value)); + + //lock (NodeValueChangeLogger) + //{ + + // Interlocked.Add(ref i, 1); + // Console.WriteLine(i); + // var getExp = $"@Get .{path}"; + // var setExp = $"@Set .{path} = {value}"; // 生成 set 表达式 + // var oldValue = SerinExpressionEvaluator.Evaluate(getExp, nodeModel, out _); + // if(oldValue != value) + // { + // Console.WriteLine($"旧值:{getExp},result : {oldValue}"); + // SerinExpressionEvaluator.Evaluate(setExp, nodeModel, out _); // 更改对应的数据 + // Console.WriteLine($"新值:{getExp},result : {SerinExpressionEvaluator.Evaluate(getExp, nodeModel, out _)}"); + // } + + //} + + } - + @@ -1487,7 +1497,7 @@ namespace Serein.NodeFlow.Env Console.WriteLine($"无法加载方法信息:{assemblyName}-{type}-{method}"); continue; } - md.MethodTips = flowName + md.MethodTips; + md.MethodAnotherName = flowName + md.MethodAnotherName; if (MethodDelegates.TryAdd(md.MethodName, del)) { methodDetails.Add(md); @@ -1702,14 +1712,23 @@ namespace Serein.NodeFlow.Env /// /// /// - private bool ConnectGerResultOfNode(NodeModelBase fromNode, + private async Task ConnectArgSourceOfNodeAsync(NodeModelBase fromNode, NodeModelBase toNode, ConnectionArgSourceType connectionArgSourceType, int argIndex) { + + if (!string.IsNullOrEmpty(toNode.MethodDetails.ParameterDetailss[argIndex].ArgDataSourceNodeGuid)) + { + //if(toNode.MethodDetails.ParameterDetailss[argIndex].ArgDataSourceType == connectionArgSourceType) + //{ + // return ; + //} + await RemoteConnectAsync(fromNode,toNode,argIndex); // 已经存在连接,将其移除 + } toNode.MethodDetails.ParameterDetailss[argIndex].ArgDataSourceNodeGuid = fromNode.Guid; toNode.MethodDetails.ParameterDetailss[argIndex].ArgDataSourceType = connectionArgSourceType; - UIContextOperation?.Invoke(() => + await UIContextOperation.InvokeAsync(() => OnNodeConnectChange?.Invoke( new NodeConnectChangeEventArgs( fromNode.Guid, // 从哪个节点开始 diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs index e5b0280..9feddf1 100644 --- a/NodeFlow/Env/FlowEnvironmentDecorator.cs +++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs @@ -34,6 +34,7 @@ namespace Serein.NodeFlow.Env private IFlowEnvironment currentFlowEnvironment; + private int _loadingProjectFlag = 0; // 使用原子自增代替锁 /// /// 传入false时,将停止数据通知。传入true时, @@ -68,9 +69,8 @@ namespace Serein.NodeFlow.Env public bool IsGlobalInterrupt => currentFlowEnvironment.IsGlobalInterrupt; - public bool IsLcR => currentFlowEnvironment.IsLcR; + public bool IsControlRemoteEnv => currentFlowEnvironment.IsControlRemoteEnv; - public bool IsRcL => currentFlowEnvironment.IsRcL; public RunState FlowState { get => currentFlowEnvironment.FlowState; set => currentFlowEnvironment.FlowState = value; } public RunState FlipFlopState { get => currentFlowEnvironment.FlipFlopState; set => currentFlowEnvironment.FlipFlopState = value; } @@ -404,14 +404,23 @@ namespace Serein.NodeFlow.Env currentFlowEnvironment.WriteLineObjToJson(obj); } - + /// + /// (用于远程)通知节点属性变更 + /// + /// 节点Guid + /// 属性路径 + /// 属性值 + /// public async Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value) { if (!IsLoadingProject()) { return; } - await currentFlowEnvironment.NotificationNodeValueChangeAsync(nodeGuid, path, value); + if (currentFlowEnvironment.IsControlRemoteEnv) + { + await currentFlowEnvironment.NotificationNodeValueChangeAsync(nodeGuid, path, value); + } } diff --git a/NodeFlow/Env/FlowFunc.cs b/NodeFlow/Env/FlowFunc.cs index b8423d2..1152329 100644 --- a/NodeFlow/Env/FlowFunc.cs +++ b/NodeFlow/Env/FlowFunc.cs @@ -53,7 +53,7 @@ namespace Serein.NodeFlow.Env methodDetails = new MethodDetails(); } var md = methodDetails.CloneOfNode(nodeModel.Env, nodeModel); - nodeModel.DisplayName = md.MethodTips; + nodeModel.DisplayName = md.MethodAnotherName; nodeModel.MethodDetails = md; diff --git a/NodeFlow/Env/MsgControllerOfServer.cs b/NodeFlow/Env/MsgControllerOfServer.cs index 064d6b0..a87163e 100644 --- a/NodeFlow/Env/MsgControllerOfServer.cs +++ b/NodeFlow/Env/MsgControllerOfServer.cs @@ -55,6 +55,7 @@ namespace Serein.NodeFlow.Env /// /// 启动带token验证的远程服务 /// + /// /// public MsgControllerOfServer(IFlowEnvironment environment, string token) { @@ -567,6 +568,7 @@ namespace Serein.NodeFlow.Env environment.SetMonitorObjState(key, isMonitor); } + /// /// 节点数据更改 /// @@ -576,6 +578,7 @@ namespace Serein.NodeFlow.Env [AutoSocketHandle(ThemeValue = EnvMsgTheme.ValueNotification)] public async Task ValueNotification(string nodeGuid, string path, string value) { + await environment.NotificationNodeValueChangeAsync(nodeGuid, path, value); } diff --git a/NodeFlow/Env/RemoteFlowEnvironment.cs b/NodeFlow/Env/RemoteFlowEnvironment.cs index 601029f..673d653 100644 --- a/NodeFlow/Env/RemoteFlowEnvironment.cs +++ b/NodeFlow/Env/RemoteFlowEnvironment.cs @@ -64,9 +64,8 @@ namespace Serein.NodeFlow.Env public bool IsGlobalInterrupt => false; - public bool IsLcR => true; + public bool IsControlRemoteEnv => true; - public bool IsRcL => false; public RunState FlowState { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public RunState FlipFlopState { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } @@ -78,6 +77,10 @@ namespace Serein.NodeFlow.Env /// 标示是否正在加载项目 /// private bool IsLoadingProject = false; + /// + /// 表示是否正在加载节点 + /// + private bool IsLoadingNode = false; public void SetConsoleOut() { @@ -666,13 +669,14 @@ namespace Serein.NodeFlow.Env /// 节点绑定的方法说明 public async Task CreateNodeAsync(NodeControlType nodeControlType, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null) { + IsLoadingNode = true; var nodeInfo = await msgClient.SendAndWaitDataAsync(EnvMsgTheme.CreateNode, new { nodeType = nodeControlType.ToString(), position = position, mdInfo = methodDetailsInfo, }); - + MethodDetails? methodDetails = null; if (!string.IsNullOrEmpty(nodeInfo.MethodName)) { @@ -683,6 +687,7 @@ namespace Serein.NodeFlow.Env var nodeModel = FlowFunc.CreateNode(this, nodeControlType, methodDetails); // 远程环境下加载节点 nodeModel.LoadInfo(nodeInfo); TryAddNode(nodeModel); + IsLoadingNode = false; // 通知UI更改 UIContextOperation.Invoke(() => @@ -816,14 +821,18 @@ namespace Serein.NodeFlow.Env public async Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value) { - //Console.WriteLine($"通知远程环境修改节点数据:{nodeGuid},name:{path},value:{value}"); + if(IsLoadingProject || IsLoadingNode) + { + return; + } + Console.WriteLine($"通知远程环境修改节点数据:{nodeGuid},name:{path},value:{value}"); - //_ = msgClient.SendAsync(EnvMsgTheme.ValueNotification, new - //{ - // nodeGuid = nodeGuid, - // path = path, - // value = value.ToString(), - //}); + _ = msgClient.SendAsync(EnvMsgTheme.ValueNotification, new + { + nodeGuid = nodeGuid, + path = path, + value = value.ToString(), + }); } } diff --git a/NodeFlow/Model/CompositeConditionNode.cs b/NodeFlow/Model/CompositeConditionNode.cs index af32f8b..eff7428 100644 --- a/NodeFlow/Model/CompositeConditionNode.cs +++ b/NodeFlow/Model/CompositeConditionNode.cs @@ -104,7 +104,7 @@ namespace Serein.NodeFlow.Model { Guid = Guid, MethodName = MethodDetails?.MethodName, - Label = DisplayName ?? "", + Label = MethodDetails?.MethodAnotherName, Type = this.GetType().ToString(), TrueNodes = trueNodes.ToArray(), FalseNodes = falseNodes.ToArray(), diff --git a/NodeFlow/Tool/NodeMethodDetailsHelper.cs b/NodeFlow/Tool/NodeMethodDetailsHelper.cs index 31cb4af..3d5e324 100644 --- a/NodeFlow/Tool/NodeMethodDetailsHelper.cs +++ b/NodeFlow/Tool/NodeMethodDetailsHelper.cs @@ -83,14 +83,14 @@ public static class NodeMethodDetailsHelper returnType = method.ReturnType; } - if (string.IsNullOrEmpty(attribute.MethodTips)){ - attribute.MethodTips = method.Name; + if (string.IsNullOrEmpty(attribute.AnotherName)){ + attribute.AnotherName = method.Name; } var asyncPrefix = "[异步]"; // IsGenericTask(returnType) ? "[async]" : ; - var methodTips = isTask ? asyncPrefix + attribute.MethodTips : attribute.MethodTips; + var methodMethodAnotherName = isTask ? asyncPrefix + attribute.AnotherName : attribute.AnotherName; @@ -101,7 +101,7 @@ public static class NodeMethodDetailsHelper MethodName = dllTypeMethodName, MethodDynamicType = attribute.MethodDynamicType, MethodLockName = attribute.LockName, - MethodTips = methodTips, + MethodAnotherName = methodMethodAnotherName, ParameterDetailss = explicitDataOfParameters, ReturnType = returnType, }; diff --git a/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs b/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs index 14f723b..afdf017 100644 --- a/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs +++ b/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs @@ -183,20 +183,32 @@ namespace Serein.Library.NodeGenerator { if (classInfo.ExitsPath(nameof(NodeValuePath.Node))) // 节点 or 自定义节点 { - sb.AddCode(5, $"((NodeModelBase)this).Env?.NotificationNodeValueChangeAsync(this.Guid, nameof({propertyName}), value); // 通知远程环境属性发生改变了"); + sb.AddCode(5, $"if (this?.Env?.IsControlRemoteEnv == true) // 正在控制远程环境时才触发"); + sb.AddCode(5, $"{{"); + sb.AddCode(6, $"this.Env?.NotificationNodeValueChangeAsync(this.Guid, nameof({propertyName}), value); // 通知远程环境属性发生改变了"); + sb.AddCode(5, $"}}"); } - else if (classInfo.ExitsPath(nameof(NodeValuePath.Method))) // 节点方法详情 + else { - sb.AddCode(5, $"NodeModel?.Env?.NotificationNodeValueChangeAsync(NodeModel.Guid, \"MethodDetails.\"+nameof({propertyName}), value); // 通知远程环境属性发生改变了"); - } - else if (classInfo.ExitsPath(nameof(NodeValuePath.Parameter))) // 节点方法入参参数描述 - { - sb.AddCode(5, "NodeModel?.Env?.NotificationNodeValueChangeAsync(NodeModel.Guid, \"MethodDetails.ParameterDetailss[\"+$\"{Index}\"+\"]." + $"\"+nameof({propertyName}),value); // 通知远程环境属性发生改变了"); - } - else if (classInfo.ExitsPath(nameof(NodeValuePath.DebugSetting))) // 节点的调试信息 - { - sb.AddCode(5, $"NodeModel?.Env?.NotificationNodeValueChangeAsync(NodeModel.Guid, \"DebugSetting.\"+nameof({propertyName}), value); // 通知远程环境属性发生改变了"); + sb.AddCode(5, $"if (NodeModel?.Env?.IsControlRemoteEnv == true) // 正在控制远程环境时才触发"); + sb.AddCode(5, $"{{"); + if (classInfo.ExitsPath(nameof(NodeValuePath.Method))) // 节点方法详情 + { + sb.AddCode(6, $"NodeModel?.Env?.NotificationNodeValueChangeAsync(NodeModel.Guid, \"MethodDetails.\"+nameof({propertyName}), value); // 通知远程环境属性发生改变了"); + } + else if (classInfo.ExitsPath(nameof(NodeValuePath.Parameter))) // 节点方法入参参数描述 + { + sb.AddCode(6, "NodeModel?.Env?.NotificationNodeValueChangeAsync(NodeModel.Guid, \"MethodDetails.ParameterDetailss[\"+$\"{Index}\"+\"]." + $"\"+nameof({propertyName}),value); // 通知远程环境属性发生改变了"); + } + else if (classInfo.ExitsPath(nameof(NodeValuePath.DebugSetting))) // 节点的调试信息 + { + + sb.AddCode(6, $"NodeModel?.Env?.NotificationNodeValueChangeAsync(NodeModel.Guid, \"DebugSetting.\"+nameof({propertyName}), value); // 通知远程环境属性发生改变了"); + + } + sb.AddCode(5, $"}}"); } + } if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.CustomCode), value => !string.IsNullOrEmpty(value))) // 是否打印 { diff --git a/WorkBench/MainWindow.xaml b/WorkBench/MainWindow.xaml index a5c1efe..de96d14 100644 --- a/WorkBench/MainWindow.xaml +++ b/WorkBench/MainWindow.xaml @@ -89,14 +89,15 @@ - + + - + @@ -209,21 +210,21 @@ Canvas.Top="{Binding ActualHeight, ElementName=FlowChartCanvas, Mode=OneWay, Con - + - - - - + + + diff --git a/WorkBench/MainWindow.xaml.cs b/WorkBench/MainWindow.xaml.cs index 920a628..e212519 100644 --- a/WorkBench/MainWindow.xaml.cs +++ b/WorkBench/MainWindow.xaml.cs @@ -368,8 +368,9 @@ namespace Serein.Workbench if (eventArgs.JunctionOfConnectionType == JunctionOfConnectionType.Invoke) { - #region 创建/删除节点之间的调用关系 ConnectionInvokeType connectionType = eventArgs.ConnectionInvokeType; + #region 创建/删除节点之间的调用关系 + #region 创建连接 if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Create) // 添加连接 { if (fromNodeControl is not INodeJunction IFormJunction || toNodeControl is not INodeJunction IToJunction) @@ -383,10 +384,10 @@ namespace Serein.Workbench // 添加连接 var connection = new ConnectionControl( - FlowChartCanvas, + FlowChartCanvas, connectionType, startJunction, - endJunction, + endJunction, () => EnvDecorator.RemoveConnectInvokeAsync(fromNodeGuid, toNodeGuid, connectionType) ); @@ -403,11 +404,16 @@ namespace Serein.Workbench } + #endregion + #region 移除连接 else if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remote) // 移除连接 { // 需要移除连接 - var removeConnections = Connections.Where(c => c.Start.MyNode.Guid.Equals(fromNodeGuid) - && c.End.MyNode.Guid.Equals(toNodeGuid)) + var removeConnections = Connections.Where(c => + c.Start.MyNode.Guid.Equals(fromNodeGuid) + && c.End.MyNode.Guid.Equals(toNodeGuid) + && (c.Start.JunctionType.ToConnectyionType() == JunctionOfConnectionType.Invoke + || c.End.JunctionType.ToConnectyionType() == JunctionOfConnectionType.Invoke)) .ToList(); @@ -417,18 +423,20 @@ namespace Serein.Workbench Connections.Remove(connection); fromNodeControl.RemoveCnnection(connection); toNodeControl.RemoveCnnection(connection); - if(NodeControls.TryGetValue(connection.End.MyNode.Guid, out var control)) + if (NodeControls.TryGetValue(connection.End.MyNode.Guid, out var control)) { JudgmentFlipFlopNode(control); // 连接关系变更时判断 } } - } + } + #endregion #endregion } else { - #region 创建/删除节点之间的参数传递关系 ConnectionArgSourceType connectionArgSourceType = eventArgs.ConnectionArgSourceType; + #region 创建/删除节点之间的参数传递关系 + #region 创建连接 if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Create) // 添加连接 { if (fromNodeControl is not INodeJunction IFormJunction || toNodeControl is not INodeJunction IToJunction) @@ -471,6 +479,8 @@ namespace Serein.Workbench } + #endregion + #region 移除连接 else if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remote) // 移除连接 { // 需要移除连接 @@ -478,11 +488,11 @@ namespace Serein.Workbench && c.End.MyNode.Guid.Equals(toNodeGuid)) .ToList(); // 获取这两个节点之间的所有连接关系 - + foreach (var connection in removeConnections) { - if(connection.End is ArgJunctionControl junctionControl && junctionControl.ArgIndex == eventArgs.ArgIndex) + if (connection.End is ArgJunctionControl junctionControl && junctionControl.ArgIndex == eventArgs.ArgIndex) { // 找到符合删除条件的连接线 connection.DeleteConnection(); // 从UI层面上移除 @@ -491,13 +501,14 @@ namespace Serein.Workbench toNodeControl.RemoveCnnection(connection); // 从节点持有的记录移除 } - + //if (NodeControls.TryGetValue(connection.End.MyNode.Guid, out var control)) //{ // JudgmentFlipFlopNode(control); // 连接关系变更时判断 //} } - } + } + #endregion #endregion } diff --git a/WorkBench/Node/View/ActionNodeControl.xaml b/WorkBench/Node/View/ActionNodeControl.xaml index bd25f67..7baaddf 100644 --- a/WorkBench/Node/View/ActionNodeControl.xaml +++ b/WorkBench/Node/View/ActionNodeControl.xaml @@ -20,7 +20,7 @@ - + @@ -66,7 +66,7 @@ - + diff --git a/WorkBench/Node/View/DllControlControl.xaml.cs b/WorkBench/Node/View/DllControlControl.xaml.cs index 8eb72ef..cb01118 100644 --- a/WorkBench/Node/View/DllControlControl.xaml.cs +++ b/WorkBench/Node/View/DllControlControl.xaml.cs @@ -66,14 +66,14 @@ namespace Serein.Workbench.Node.View /// /// 向指定面板添加类型的文本块 /// - /// 要添加的类型 - /// 要添加到的面板 + /// 要添加的方法信息 + /// 要添加到的面板 private void AddTypeToListBox(MethodDetailsInfo mdInfo, ListBox listBox) { // 创建一个新的 TextBlock 并设置其属性 TextBlock typeText = new TextBlock { - Text = $"{mdInfo.MethodTips}", + Text = $"{mdInfo.MethodAnotherName} - {mdInfo.MethodName}", Margin = new Thickness(10, 2, 0, 0), Tag = mdInfo }; diff --git a/WorkBench/Node/View/FlipflopNodeControl.xaml b/WorkBench/Node/View/FlipflopNodeControl.xaml index d6e89e0..5715eb2 100644 --- a/WorkBench/Node/View/FlipflopNodeControl.xaml +++ b/WorkBench/Node/View/FlipflopNodeControl.xaml @@ -22,7 +22,7 @@ - + @@ -47,7 +47,7 @@ - + diff --git a/WorkBench/Themes/NodeTreeItemViewControl.xaml.cs b/WorkBench/Themes/NodeTreeItemViewControl.xaml.cs index 113344d..4f77fb8 100644 --- a/WorkBench/Themes/NodeTreeItemViewControl.xaml.cs +++ b/WorkBench/Themes/NodeTreeItemViewControl.xaml.cs @@ -56,7 +56,7 @@ namespace Serein.Workbench.Themes {ConnectionInvokeType.IsError, []}, } }; - string? itemName = rootNodeModel.MethodDetails?.MethodTips; + string? itemName = rootNodeModel.MethodDetails?.MethodAnotherName; if (string.IsNullOrEmpty(itemName)) { itemName = rootNodeModel.ControlType.ToString(); @@ -123,7 +123,7 @@ namespace Serein.Workbench.Themes RootNode = child, ChildNodes = child.SuccessorNodes, }; - string? itemName = child?.MethodDetails?.MethodTips; + string? itemName = child?.MethodDetails?.MethodAnotherName; if (string.IsNullOrEmpty(itemName)) { itemName = child?.ControlType.ToString(); @@ -186,7 +186,7 @@ namespace Serein.Workbench.Themes ChildNodes = childNodeModel.SuccessorNodes, }; - string? itemName = childNodeModel?.MethodDetails?.MethodTips; + string? itemName = childNodeModel?.MethodDetails?.MethodAnotherName; if (string.IsNullOrEmpty(itemName)) { itemName = childNodeModel?.ControlType.ToString();