mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
修改了远程环境的节点加载流程、容器节点子节点的位置关系
This commit is contained in:
@@ -38,6 +38,14 @@
|
||||
/// </summary>
|
||||
public const string RemoveNode = nameof(RemoveNode);
|
||||
/// <summary>
|
||||
/// 尝试放置节点
|
||||
/// </summary>
|
||||
public const string PlaceNode = nameof(PlaceNode);
|
||||
/// <summary>
|
||||
/// 尝试取出节点
|
||||
/// </summary>
|
||||
public const string TakeOutNode = nameof(TakeOutNode);
|
||||
/// <summary>
|
||||
/// 尝试连接两个节点的方法调用关系
|
||||
/// </summary>
|
||||
public const string ConnectInvokeNode = nameof(ConnectInvokeNode);
|
||||
|
||||
@@ -152,9 +152,14 @@ namespace Serein.NodeFlow.Env
|
||||
public event NodeRemoveHandler? OnNodeRemove;
|
||||
|
||||
/// <summary>
|
||||
/// 节点父子关系发生改变事件
|
||||
/// 节点放置事件
|
||||
/// </summary>
|
||||
public event NodeContainerChildChangeHandler OnNodeParentChildChange;
|
||||
public event NodePlaceHandler OnNodePlace;
|
||||
|
||||
/// <summary>
|
||||
/// 节点取出事件
|
||||
/// </summary>
|
||||
public event NodeTakeOutHandler OnNodeTakeOut;
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点变化事件
|
||||
@@ -350,15 +355,6 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
#region 环境对外接口
|
||||
|
||||
///// <summary>
|
||||
///// 重定向Console输出
|
||||
///// </summary>
|
||||
//public void SetConsoleOut()
|
||||
//{
|
||||
// var logTextWriter = new LogTextWriter(msg => Output(msg));
|
||||
// Console.SetOut(logTextWriter);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 输出信息
|
||||
/// </summary>
|
||||
@@ -375,25 +371,11 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// 使用JSON处理库输出对象信息
|
||||
///// </summary>
|
||||
///// <param name="obj"></param>
|
||||
//public void WriteLineObjToJson(object obj)
|
||||
//{
|
||||
// var msg = JsonConvert.SerializeObject(obj);
|
||||
// if (OperatingSystem.IsWindows())
|
||||
// {
|
||||
// UIContextOperation?.Invoke(() => OnEnvOut?.Invoke(msg + Environment.NewLine));
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 异步运行
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task StartAsync()
|
||||
public async Task<bool> StartFlowAsync()
|
||||
{
|
||||
ChannelFlowInterrupt?.CancelAllTasks();
|
||||
flowStarter = new FlowStarter();
|
||||
@@ -416,13 +398,16 @@ namespace Serein.NodeFlow.Env
|
||||
// 注册封装好的UI线程上下文
|
||||
IOC.CustomRegisterInstance(typeof(UIContextOperation).FullName, this.UIContextOperation, false);
|
||||
}
|
||||
|
||||
await flowStarter.RunAsync(this, nodes, autoRegisterTypes, initMethods, loadMethods, exitMethods);
|
||||
|
||||
if (FlipFlopState == RunState.Completion)
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
ExitFlow(); // 未运行触发器时,才会调用结束方法
|
||||
}
|
||||
await flowStarter.RunAsync(this, nodes, autoRegisterTypes, initMethods, loadMethods, exitMethods);
|
||||
if (FlipFlopState == RunState.Completion)
|
||||
{
|
||||
await ExitFlowAsync(); // 未运行触发器时,才会调用结束方法
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -431,20 +416,20 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
/// <param name="startNodeGuid"></param>
|
||||
/// <returns></returns>
|
||||
public async Task StartAsyncInSelectNode(string startNodeGuid)
|
||||
public async Task<bool> StartAsyncInSelectNode(string startNodeGuid)
|
||||
{
|
||||
|
||||
if (flowStarter is null)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, "没有启动流程,无法运行单个节点");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (true || FlowState == RunState.Running || FlipFlopState == RunState.Running)
|
||||
{
|
||||
NodeModelBase? nodeModel = GuidToModel(startNodeGuid);
|
||||
if (nodeModel is null || nodeModel is SingleFlipflopNode)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
//var getExp = "@get .DebugSetting.IsEnable";
|
||||
//var getExpResult1 = SerinExpressionEvaluator.Evaluate(getExp, nodeModel,out _);
|
||||
@@ -453,10 +438,11 @@ namespace Serein.NodeFlow.Env
|
||||
//var getExpResult2 = SerinExpressionEvaluator.Evaluate(getExp, nodeModel, out _);
|
||||
|
||||
await flowStarter.StartFlowInSelectNodeAsync(this, nodeModel);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,21 +464,20 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 结束流程
|
||||
/// </summary>
|
||||
public void ExitFlow()
|
||||
public Task<bool> ExitFlowAsync()
|
||||
{
|
||||
ChannelFlowInterrupt?.CancelAllTasks();
|
||||
flowStarter?.Exit();
|
||||
UIContextOperation?.Invoke(() => OnFlowRunComplete?.Invoke(new FlowEventArgs()));
|
||||
flowStarter = null;
|
||||
GC.Collect();
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激活全局触发器
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
// [AutoSocketHandle]
|
||||
public void ActivateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
@@ -512,7 +497,6 @@ namespace Serein.NodeFlow.Env
|
||||
/// 关闭全局触发器
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
// [AutoSocketHandle]
|
||||
public void TerminateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
var nodeModel = GuidToModel(nodeGuid);
|
||||
@@ -541,16 +525,6 @@ namespace Serein.NodeFlow.Env
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有
|
||||
/// </summary>
|
||||
public void ClearAll()
|
||||
{
|
||||
//LoadedAssemblyPaths.Clear();
|
||||
//NodeLibrarys.Clear();
|
||||
//MethodDetailss.Clear();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存项目
|
||||
@@ -582,7 +556,7 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
_ = LoadNodeInfosAsync(projectData.Nodes.ToList());
|
||||
SetStartNode(projectData.StartNode);
|
||||
SetStartNodeAsync(projectData.StartNode);
|
||||
|
||||
}
|
||||
|
||||
@@ -686,7 +660,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
/// <param name="assemblyName"></param>
|
||||
/// <returns></returns>
|
||||
public bool UnloadLibrary(string assemblyName)
|
||||
public bool TryUnloadLibrary(string assemblyName)
|
||||
{
|
||||
// 获取与此程序集相关的节点
|
||||
var groupedNodes = NodeModels.Values.Where(node => node.MethodDetails.AssemblyName.Equals(assemblyName)).ToArray();
|
||||
@@ -773,7 +747,6 @@ namespace Serein.NodeFlow.Env
|
||||
/// <returns></returns>
|
||||
public Task LoadNodeInfosAsync(List<NodeInfo> nodeInfos)
|
||||
{
|
||||
List<NodeInfo> needPlaceNodeInfos = [];
|
||||
#region 从NodeInfo创建NodeModel
|
||||
foreach (NodeInfo? nodeInfo in nodeInfos)
|
||||
{
|
||||
@@ -805,27 +778,36 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
nodeModel.LoadInfo(nodeInfo); // 创建节点model
|
||||
TryAddNode(nodeModel); // 加载项目时将节点加载到环境中
|
||||
if (!string.IsNullOrEmpty(nodeInfo.ParentNodeGuid) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var parentNode))
|
||||
{
|
||||
needPlaceNodeInfos.Add(nodeInfo); // 需要重新放置的节点
|
||||
}
|
||||
|
||||
UIContextOperation?.Invoke(() =>
|
||||
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position))); // 添加到UI上
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 重新放置节点
|
||||
foreach (NodeInfo nodeInfo in needPlaceNodeInfos)
|
||||
|
||||
List<NodeInfo> needPlaceNodeInfos = [];
|
||||
foreach (NodeInfo? nodeInfo in nodeInfos)
|
||||
{
|
||||
if (NodeModels.TryGetValue(nodeInfo.Guid, out var childNode) &&
|
||||
if (!string.IsNullOrEmpty(nodeInfo.ParentNodeGuid) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var parentNode))
|
||||
{
|
||||
childNode.ParentNode = parentNode;
|
||||
parentNode.ChildrenNode.Add(childNode);
|
||||
UIContextOperation?.Invoke(() => OnNodeParentChildChange?.Invoke(
|
||||
new NodeContainerChildChangeEventArgs(childNode.Guid, parentNode.Guid,
|
||||
NodeContainerChildChangeEventArgs.Type.Place)));
|
||||
needPlaceNodeInfos.Add(nodeInfo); // 需要重新放置的节点
|
||||
}
|
||||
}
|
||||
|
||||
foreach (NodeInfo nodeInfo in needPlaceNodeInfos)
|
||||
{
|
||||
if (NodeModels.TryGetValue(nodeInfo.Guid, out var nodeMoel) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var containerNode)
|
||||
&& containerNode is INodeContainer nodeContainer)
|
||||
{
|
||||
nodeMoel.ContainerNode = containerNode; // 放置节点
|
||||
containerNode.ChildrenNode.Add(nodeMoel);
|
||||
nodeContainer.PlaceNode(nodeMoel);
|
||||
|
||||
UIContextOperation?.Invoke(() => OnNodePlace?.Invoke(
|
||||
new NodePlaceEventArgs(nodeMoel.Guid, containerNode.Guid)));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -935,40 +917,57 @@ namespace Serein.NodeFlow.Env
|
||||
return Task.FromResult(nodeInfo);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将节点放置在容器中/从容器中取出
|
||||
/// 将节点放置在容器中
|
||||
/// </summary>
|
||||
/// <param name="childNodeGuid">子节点(主要节点)</param>
|
||||
/// <param name="parentNodeGuid">父节点</param>
|
||||
/// <param name="isPlace">是否组合(反之为分解节点组合关系)</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ChangeNodeContainerChild(string childNodeGuid, string parentNodeGuid, bool isPlace)
|
||||
public async Task<bool> PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid)
|
||||
{
|
||||
// 获取起始节点与目标节点
|
||||
var childNode = GuidToModel(childNodeGuid);
|
||||
var parentNode = GuidToModel(parentNodeGuid);
|
||||
if (childNode is null || parentNode is null || parentNode is not INodeContainer nodeContainer) return false;
|
||||
// 获取目标节点与容器节点
|
||||
var nodeMoel = GuidToModel(nodeGuid);
|
||||
if (nodeMoel is null ) return false;
|
||||
|
||||
if (isPlace)
|
||||
if(nodeMoel.ContainerNode is INodeContainer tmpContainer)
|
||||
{
|
||||
// 放置节点
|
||||
parentNode.ChildrenNode.Add(childNode);
|
||||
childNode.ParentNode = parentNode;
|
||||
nodeContainer.PlaceNode(childNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 取出节点
|
||||
parentNode.ChildrenNode.Remove(childNode);
|
||||
childNode.ParentNode = null;
|
||||
nodeContainer.TakeOutNode(childNode);
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"节点放置失败,节点[{nodeGuid}]已经放置于容器节点[{((NodeModelBase)tmpContainer).Guid}]");
|
||||
return false;
|
||||
}
|
||||
|
||||
OnNodeParentChildChange?.Invoke(new NodeContainerChildChangeEventArgs(childNodeGuid, parentNodeGuid,
|
||||
isPlace ? NodeContainerChildChangeEventArgs.Type.Place : NodeContainerChildChangeEventArgs.Type.TakeOut));
|
||||
var containerNode = GuidToModel(containerNodeGuid);
|
||||
if (containerNode is not INodeContainer nodeContainer) return false;
|
||||
|
||||
nodeMoel.ContainerNode = containerNode; // 放置节点
|
||||
containerNode.ChildrenNode.Add(nodeMoel);
|
||||
nodeContainer.PlaceNode(nodeMoel);
|
||||
OnNodePlace?.Invoke(new NodePlaceEventArgs(nodeGuid, containerNodeGuid)); // 通知UI更改节点放置位置
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将节点从容器节点中脱离
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> TakeOutNodeToContainerAsync(string nodeGuid)
|
||||
{
|
||||
// 获取目标节点与容器节点
|
||||
var nodeMoel = GuidToModel(nodeGuid);
|
||||
if (nodeMoel is null) return false;
|
||||
|
||||
if(nodeMoel.ContainerNode is not INodeContainer nodeContainer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
nodeContainer.TakeOutNode(nodeMoel); // 从容器节点取出
|
||||
nodeMoel.ContainerNode = null; // 取消映射关系
|
||||
|
||||
OnNodeTakeOut?.Invoke(new NodeTakeOutEventArgs(nodeGuid)); // 重新放置在画布上
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 移除节点
|
||||
/// </summary>
|
||||
@@ -1232,11 +1231,13 @@ namespace Serein.NodeFlow.Env
|
||||
/// 设置起点控件
|
||||
/// </summary>
|
||||
/// <param name="newNodeGuid"></param>
|
||||
public void SetStartNode(string newNodeGuid)
|
||||
public Task<string> SetStartNodeAsync(string newNodeGuid)
|
||||
{
|
||||
var newStartNodeModel = GuidToModel(newNodeGuid);
|
||||
if (newStartNodeModel is null) return;
|
||||
if (newStartNodeModel is null)
|
||||
return Task.FromResult(StartNode?.Guid ?? string.Empty);
|
||||
SetStartNode(newStartNodeModel);
|
||||
return Task.FromResult(StartNode?.Guid ?? string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1893,11 +1894,11 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
var oldNodeGuid = StartNode?.Guid;
|
||||
StartNode = newStartNode;
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(oldNodeGuid, StartNode.Guid)));
|
||||
}
|
||||
|
||||
UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(oldNodeGuid, StartNode.Guid)));
|
||||
|
||||
//if (OperatingSystem.IsWindows())
|
||||
//{
|
||||
// }
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
@@ -1910,7 +1911,7 @@ namespace Serein.NodeFlow.Env
|
||||
// {
|
||||
// UIContextOperation?.Invoke(() => OnEnvOut?.Invoke(msg));
|
||||
// }
|
||||
|
||||
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -3,6 +3,7 @@ using Serein.Library.Api;
|
||||
using Serein.Library.FlowNode;
|
||||
using Serein.Library.Utils;
|
||||
using Serein.NodeFlow.Tool;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Serein.NodeFlow.Env
|
||||
{
|
||||
@@ -121,13 +122,16 @@ namespace Serein.NodeFlow.Env
|
||||
remove { currentFlowEnvironment.OnNodeRemove -= value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节点父子关系发生改变事件
|
||||
/// </summary>
|
||||
public event NodeContainerChildChangeHandler OnNodeParentChildChange
|
||||
public event NodePlaceHandler OnNodePlace
|
||||
{
|
||||
add { currentFlowEnvironment.OnNodeParentChildChange += value; }
|
||||
remove { currentFlowEnvironment.OnNodeParentChildChange -= value; }
|
||||
add { currentFlowEnvironment.OnNodePlace += value; }
|
||||
remove { currentFlowEnvironment.OnNodePlace -= value; }
|
||||
}
|
||||
|
||||
public event NodeTakeOutHandler OnNodeTakeOut
|
||||
{
|
||||
add { currentFlowEnvironment.OnNodeTakeOut += value; }
|
||||
remove { currentFlowEnvironment.OnNodeTakeOut -= value; }
|
||||
}
|
||||
|
||||
public event StartNodeChangeHandler OnStartNodeChange
|
||||
@@ -203,10 +207,6 @@ namespace Serein.NodeFlow.Env
|
||||
return await currentFlowEnvironment.CheckObjMonitorStateAsync(key);
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
currentFlowEnvironment.ClearAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在两个节点之间创建连接关系
|
||||
@@ -287,27 +287,35 @@ namespace Serein.NodeFlow.Env
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将节点放置在容器中/从容器中取出
|
||||
/// 将节点放置在容器中
|
||||
/// </summary>
|
||||
/// <param name="childNodeGuid">子节点(主要节点)</param>
|
||||
/// <param name="parentNodeGuid">父节点</param>
|
||||
/// <param name="isPlace">是否组合(反之为分解节点组合关系)</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ChangeNodeContainerChild(string childNodeGuid, string parentNodeGuid, bool isAssembly)
|
||||
public async Task<bool> PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid)
|
||||
{
|
||||
SetProjectLoadingFlag(false);
|
||||
var result = await currentFlowEnvironment.ChangeNodeContainerChild(childNodeGuid, parentNodeGuid, isAssembly); // 装饰器调用
|
||||
var result = await currentFlowEnvironment.PlaceNodeToContainerAsync(nodeGuid, containerNodeGuid); // 装饰器调用
|
||||
SetProjectLoadingFlag(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将节点从容器中脱离
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> TakeOutNodeToContainerAsync(string nodeGuid)
|
||||
{
|
||||
SetProjectLoadingFlag(false);
|
||||
var result = await currentFlowEnvironment.TakeOutNodeToContainerAsync(nodeGuid); // 装饰器调用
|
||||
SetProjectLoadingFlag(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ExitFlow()
|
||||
public async Task<bool> ExitFlowAsync()
|
||||
{
|
||||
currentFlowEnvironment.ExitFlow();
|
||||
return await currentFlowEnvironment.ExitFlowAsync();
|
||||
}
|
||||
|
||||
public void ExitRemoteEnv()
|
||||
@@ -369,9 +377,9 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
|
||||
public bool UnloadLibrary(string assemblyName)
|
||||
public bool TryUnloadLibrary(string assemblyName)
|
||||
{
|
||||
return currentFlowEnvironment.UnloadLibrary(assemblyName);
|
||||
return currentFlowEnvironment.TryUnloadLibrary(assemblyName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -441,19 +449,19 @@ namespace Serein.NodeFlow.Env
|
||||
return await currentFlowEnvironment.SetNodeInterruptAsync(nodeGuid, isInterrupt);
|
||||
}
|
||||
|
||||
public void SetStartNode(string nodeGuid)
|
||||
public async Task<string> SetStartNodeAsync(string nodeGuid)
|
||||
{
|
||||
currentFlowEnvironment.SetStartNode(nodeGuid);
|
||||
return await currentFlowEnvironment.SetStartNodeAsync(nodeGuid);
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
public async Task<bool> StartFlowAsync()
|
||||
{
|
||||
await currentFlowEnvironment.StartAsync();
|
||||
return await currentFlowEnvironment.StartFlowAsync();
|
||||
}
|
||||
|
||||
public async Task StartAsyncInSelectNode(string startNodeGuid)
|
||||
public async Task<bool> StartAsyncInSelectNode(string startNodeGuid)
|
||||
{
|
||||
await currentFlowEnvironment.StartAsyncInSelectNode(startNodeGuid);
|
||||
return await currentFlowEnvironment.StartAsyncInSelectNode(startNodeGuid);
|
||||
}
|
||||
|
||||
public async Task<object> InvokeNodeAsync(IDynamicContext context, string nodeGuid)
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace Serein.NodeFlow.Env
|
||||
/// <exception cref="NotImplementedException">超时触发</exception>
|
||||
public async Task SendAsync(string theme, object? data = null, int overtimeInMs = 100)
|
||||
{
|
||||
|
||||
var msgId = MsgIdHelper.GenerateId().ToString();
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"[{msgId}] => {theme}");
|
||||
await SendCommandAsync(msgId, theme, data); // 客户端发送消息
|
||||
@@ -62,12 +61,17 @@ namespace Serein.NodeFlow.Env
|
||||
public async Task<TResult> SendAndWaitDataAsync<TResult>(string theme, object? data = null, int overtimeInMs = 50)
|
||||
{
|
||||
var msgId = MsgIdHelper.GenerateId().ToString();
|
||||
//_ = Task.Run(async () =>
|
||||
//{
|
||||
// await Task.Delay(500);
|
||||
//});
|
||||
await SendCommandAsync(msgId, theme, data); // 客户端发送消息
|
||||
return (await remoteFlowEnvironment.WaitTriggerAsync<TResult>(msgId)).Value;
|
||||
_ = SendCommandAsync(msgId, theme, data); // 客户端发送消息
|
||||
var result = await remoteFlowEnvironment.WaitTriggerAsync<TResult>(msgId);
|
||||
if (result.Type == TriggerDescription.Overtime)
|
||||
{
|
||||
throw new Exception($"主题【{theme}】异常,服务端未响应");
|
||||
}
|
||||
else if (result.Type == TriggerDescription.TypeInconsistency)
|
||||
{
|
||||
throw new Exception($"主题【{theme}】异常,服务端返回数据类型与预期不一致{result.Value?.GetType()}");
|
||||
}
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,12 +100,66 @@ namespace Serein.NodeFlow.Env
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, sereinProjectData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始流程
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.StartFlow, IsReturnValue = false)]
|
||||
public void StartFlow([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, state);
|
||||
}
|
||||
/// <summary>
|
||||
/// 结束流程
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.ExitFlow, IsReturnValue = false)]
|
||||
public void ExitFlow([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置了某个节点为起始节点
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.SetStartNode, IsReturnValue = false)]
|
||||
public void SetStartNode([UseMsgId] string msgId, string nodeGuid)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, nodeGuid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从某个节点开始运行
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.StartFlowInSelectNode, IsReturnValue = false)]
|
||||
public void StartFlowInSelectNode([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置节点的中断
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.SetNodeInterrupt, IsReturnValue = false)]
|
||||
public void SetNodeInterrupt([UseMsgId] string msgId)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync<object>(msgId, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加中断监视表达式
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.AddInterruptExpression, IsReturnValue = false)]
|
||||
public void AddInterruptExpression([UseMsgId] string msgId)
|
||||
{
|
||||
@@ -109,43 +167,77 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建节点
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="nodeInfo"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.CreateNode, IsReturnValue = false)]
|
||||
public void CreateNode([UseMsgId] string msgId, [UseData] NodeInfo nodeInfo)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, nodeInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除节点
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.RemoveNode, IsReturnValue = false)]
|
||||
public void RemoveNode([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建节点之间的调用关系
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.ConnectInvokeNode, IsReturnValue = false)]
|
||||
public void ConnectInvokeNode([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除节点之间的调用关系
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.RemoveInvokeConnect, IsReturnValue = false)]
|
||||
public void RemoveInvokeConnect([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建节点之间参数获取关系
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.ConnectArgSourceNode, IsReturnValue = false)]
|
||||
public void ConnectArgSourceNode([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除节点之间参数获取关系
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.RemoveArgSourceConnect, IsReturnValue = false)]
|
||||
public void RemoveArgSourceConnect([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 改变参数
|
||||
/// </summary>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="state"></param>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.ChangeParameter, IsReturnValue = false)]
|
||||
public void ChangeParameter([UseMsgId] string msgId, bool state)
|
||||
{
|
||||
@@ -153,8 +245,6 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
@@ -172,10 +172,14 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.StartFlow)]
|
||||
private async Task StartAsync()
|
||||
private async Task<object> StartAsync()
|
||||
{
|
||||
var uiContextOperation = environment.IOC.Get<UIContextOperation>();
|
||||
await environment.StartAsync();
|
||||
var state = await environment.StartFlowAsync();
|
||||
return new
|
||||
{
|
||||
state = state,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -184,19 +188,26 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <returns></returns>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.StartFlowInSelectNode)]
|
||||
private async Task StartAsyncInSelectNode(string nodeGuid)
|
||||
private async Task<object> StartAsyncInSelectNode(string nodeGuid)
|
||||
{
|
||||
await environment.StartAsyncInSelectNode(nodeGuid);
|
||||
var state = await environment.StartAsyncInSelectNode(nodeGuid);
|
||||
return new
|
||||
{
|
||||
state = state,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结束流程
|
||||
/// </summary>
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.ExitFlow)]
|
||||
private void ExitFlow()
|
||||
private async Task<object> ExitFlow()
|
||||
{
|
||||
environment.ExitFlow();
|
||||
|
||||
var state = await environment.ExitFlowAsync();
|
||||
return new
|
||||
{
|
||||
state = state,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -519,7 +530,7 @@ namespace Serein.NodeFlow.Env
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.SetStartNode)]
|
||||
public void SetStartNode(string nodeGuid)
|
||||
{
|
||||
environment.SetStartNode(nodeGuid);
|
||||
environment.SetStartNodeAsync(nodeGuid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -55,10 +55,8 @@ namespace Serein.NodeFlow.Env
|
||||
public event NodeConnectChangeHandler OnNodeConnectChange;
|
||||
public event NodeCreateHandler OnNodeCreate;
|
||||
public event NodeRemoveHandler OnNodeRemove;
|
||||
/// <summary>
|
||||
/// 节点父子关系发生改变事件
|
||||
/// </summary>
|
||||
public event NodeContainerChildChangeHandler OnNodeParentChildChange;
|
||||
public event NodePlaceHandler OnNodePlace;
|
||||
public event NodeTakeOutHandler OnNodeTakeOut;
|
||||
public event StartNodeChangeHandler OnStartNodeChange;
|
||||
public event FlowRunCompleteHandler OnFlowRunComplete;
|
||||
public event MonitorObjectChangeHandler OnMonitorObjectChange;
|
||||
@@ -117,11 +115,6 @@ namespace Serein.NodeFlow.Env
|
||||
OnEnvOut?.Invoke(type, message);
|
||||
}
|
||||
|
||||
public void WriteLineObjToJson(object obj)
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:WriteLineObjToJson");
|
||||
}
|
||||
|
||||
public async Task StartRemoteServerAsync(int port = 7525)
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:StartRemoteServerAsync");
|
||||
@@ -133,10 +126,14 @@ namespace Serein.NodeFlow.Env
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:StopRemoteServer");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取远程环境
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<SereinProjectData> GetProjectInfoAsync()
|
||||
{
|
||||
var prjectInfo = await msgClient.SendAndWaitDataAsync<SereinProjectData>(EnvMsgTheme.GetProjectInfo); // 等待服务器返回项目信息
|
||||
return prjectInfo;
|
||||
var projectData = await msgClient.SendAndWaitDataAsync<SereinProjectData>(EnvMsgTheme.GetProjectInfo); // 等待服务器返回项目信息
|
||||
return projectData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,9 +173,9 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
_ = LoadNodeInfosAsync(flowEnvInfo.Project.Nodes.ToList());
|
||||
SetStartNode(flowEnvInfo.Project.StartNode); // 设置流程起点
|
||||
|
||||
LoadNodeInfos(flowEnvInfo.Project.Nodes.ToList()); // 加载节点
|
||||
_ = SetStartNodeAsync(flowEnvInfo.Project.StartNode); // 设置流程起点
|
||||
UIContextOperation?.Invoke(() =>
|
||||
{
|
||||
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs()); // 加载完成
|
||||
@@ -341,87 +338,95 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private bool TryAddNode(NodeModelBase nodeModel)
|
||||
{
|
||||
//nodeModel.Guid ??= Guid.NewGuid().ToString();
|
||||
NodeModels[nodeModel.Guid] = nodeModel;
|
||||
|
||||
// 如果是触发器,则需要添加到专属集合中
|
||||
//if (nodeModel is SingleFlipflopNode flipflopNode)
|
||||
//{
|
||||
// var guid = flipflopNode.Guid;
|
||||
// if (!FlipflopNodes.Exists(it => it.Guid.Equals(guid)))
|
||||
// {
|
||||
// FlipflopNodes.Add(flipflopNode);
|
||||
// }
|
||||
//}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从远程环境获取项目信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<FlowEnvInfo> GetEnvInfoAsync()
|
||||
{
|
||||
var envInfo = await msgClient.SendAndWaitDataAsync<FlowEnvInfo>(EnvMsgTheme.GetEnvInfo);
|
||||
return envInfo;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 连接到远程环境
|
||||
/// </summary>
|
||||
/// <param name="addres"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token)
|
||||
{
|
||||
await Console.Out.WriteLineAsync("远程环境尚未实现的接口:ConnectRemoteEnv");
|
||||
return (false, null);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 退出远程环境
|
||||
/// </summary>
|
||||
public void ExitRemoteEnv()
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:ExitRemoteEnv");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (待更新)加载类库
|
||||
/// </summary>
|
||||
/// <param name="dllPath"></param>
|
||||
public void LoadLibrary(string dllPath)
|
||||
{
|
||||
// 将dll文件发送到远程环境,由远程环境进行加载
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:LoadDll");
|
||||
}
|
||||
|
||||
public bool UnloadLibrary(string assemblyName)
|
||||
/// <summary>
|
||||
/// (待更新)卸载类库
|
||||
/// </summary>
|
||||
/// <param name="assemblyName"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryUnloadLibrary(string assemblyName)
|
||||
{
|
||||
// 尝试移除远程环境中的加载了的依赖
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:RemoteDll");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:ClearAll");
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
/// <summary>
|
||||
/// 启动远程环境的流程
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> StartFlowAsync()
|
||||
{
|
||||
// 远程环境下不需要UI上下文
|
||||
await msgClient.SendAsync(EnvMsgTheme.StartFlow);
|
||||
var result = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.StartFlow);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task StartAsyncInSelectNode(string startNodeGuid)
|
||||
/// <summary>
|
||||
/// 从选定的节点开始运行
|
||||
/// </summary>
|
||||
/// <param name="startNodeGuid"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> StartAsyncInSelectNode(string startNodeGuid)
|
||||
{
|
||||
_ = msgClient.SendAsync(EnvMsgTheme.StartFlowInSelectNode, new
|
||||
var result = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.StartFlowInSelectNode, new
|
||||
{
|
||||
nodeGuid = startNodeGuid
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public async void ExitFlow()
|
||||
/// <summary>
|
||||
/// 结束远程环境的流程运行
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ExitFlowAsync()
|
||||
{
|
||||
await msgClient.SendAsync(EnvMsgTheme.ExitFlow, null);
|
||||
var result = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.ExitFlow, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移动节点,通知远程环境也一起移动,保持相对位置一致
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
public void MoveNode(string nodeGuid, double x, double y)
|
||||
{
|
||||
//UIContextOperation?.Invoke(() =>
|
||||
@@ -443,26 +448,26 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetStartNode(string nodeGuid)
|
||||
|
||||
/// <summary>
|
||||
/// 设置远程环境的流程起点节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">尝试设置为起始节点的节点Guid</param>
|
||||
/// <returns>被设置为起始节点的Guid</returns>
|
||||
public async Task<string> SetStartNodeAsync(string nodeGuid)
|
||||
{
|
||||
_ = msgClient.SendAsync(EnvMsgTheme.SetStartNode, new
|
||||
var newNodeGuid = await msgClient.SendAndWaitDataAsync<string>(EnvMsgTheme.SetStartNode, new
|
||||
{
|
||||
nodeGuid
|
||||
});
|
||||
UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(nodeGuid,nodeGuid)));
|
||||
}
|
||||
|
||||
public async Task<object> InvokeNodeAsync(IDynamicContext context, string nodeGuid)
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现接口 InvokeNodeAsync");
|
||||
//_ = msgClient.SendAsync(EnvMsgTheme.InvokeNodeAsync, new
|
||||
//{
|
||||
// nodeGuid
|
||||
//});
|
||||
return null;
|
||||
if (NodeModels.TryGetValue(newNodeGuid, out var nodeModel)) // 存在节点
|
||||
{
|
||||
UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(nodeGuid, newNodeGuid)));
|
||||
}
|
||||
return newNodeGuid;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 在两个节点之间创建方法调用关系
|
||||
/// </summary>
|
||||
@@ -599,7 +604,7 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置两个节点某个类型的方法调用关系为优先调用
|
||||
/// (待更新)设置两个节点某个类型的方法调用关系为优先调用
|
||||
/// </summary>
|
||||
/// <param name="fromNodeGuid">起始节点</param>
|
||||
/// <param name="toNodeGuid">目标节点</param>
|
||||
@@ -610,6 +615,7 @@ namespace Serein.NodeFlow.Env
|
||||
this.WriteLine(InfoType.WARN, "远程环境尚未实现的接口(重要,会尽快实现):SetConnectPriorityInvoke");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除两个节点之间的方法调用关系
|
||||
/// </summary>
|
||||
@@ -637,6 +643,7 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除连接节点之间参数传递的关系
|
||||
/// </summary>
|
||||
@@ -670,13 +677,369 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 从节点信息集合批量加载节点控件
|
||||
/// </summary>
|
||||
/// <param name="List<NodeInfo>">节点信息</param>
|
||||
/// <param name="position">需要加载的位置</param>
|
||||
/// <param name="nodeInfos">节点信息</param>
|
||||
/// <returns></returns>
|
||||
public async Task LoadNodeInfosAsync(List<NodeInfo> nodeInfos)
|
||||
{
|
||||
List<NodeInfo> needPlaceNodeInfos = [];
|
||||
if (IsLoadingProject || IsLoadingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<NodeInfo> loadSuuccessNodes = new List<NodeInfo>(); // 加载成功的节点信息
|
||||
List<NodeInfo> loadFailureNodes = new List<NodeInfo>(); // 加载失败的节点信息
|
||||
List<NodeInfo> needPlaceNodeInfos = new List<NodeInfo>(); // 需要重新放置的节点
|
||||
|
||||
#region 尝试从节点信息加载节点
|
||||
foreach (NodeInfo? nodeInfo in nodeInfos)
|
||||
{
|
||||
if (!EnumHelper.TryConvertEnum<NodeControlType>(nodeInfo.Type, out var controlType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
NodeInfo newNodeInfo;
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(nodeInfo.MethodName))
|
||||
{
|
||||
if (!MethodDetailss.TryGetValue(nodeInfo.MethodName, out var methodDetails))
|
||||
{
|
||||
loadFailureNodes.Add(nodeInfo);
|
||||
continue; // 有方法名称,但本地没有缓存的相关方法信息,跳过
|
||||
}
|
||||
// 加载远程环境时尝试获取方法信息
|
||||
newNodeInfo = await CreateNodeAsync(controlType, nodeInfo.Position, methodDetails.ToInfo());
|
||||
}
|
||||
else
|
||||
{
|
||||
newNodeInfo = await CreateNodeAsync(controlType, nodeInfo.Position);
|
||||
}
|
||||
loadSuuccessNodes.Add(nodeInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SereinEnv.WriteLine(ex);
|
||||
loadFailureNodes.Add(nodeInfo);
|
||||
continue; // 跳过加载失败的节点
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
// 远程环境无法加载的节点,输出信息
|
||||
foreach (var f_node in loadFailureNodes)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.INFO, "无法加载的节点Guid:" + f_node.Guid);
|
||||
}
|
||||
|
||||
#region 尝试重新放置节点的位置
|
||||
// 判断加载的节点是否需要放置在容器中
|
||||
foreach (var nodeInfo in loadSuuccessNodes)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(nodeInfo.ParentNodeGuid) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var parentNode))
|
||||
{
|
||||
needPlaceNodeInfos.Add(nodeInfo); // 需要重新放置的节点
|
||||
}
|
||||
}
|
||||
loadSuuccessNodes.Clear();
|
||||
loadFailureNodes.Clear();
|
||||
foreach (var nodeInfo in needPlaceNodeInfos)
|
||||
{
|
||||
// 通知远程调整节点放置位置
|
||||
var isSuuccess = await PlaceNodeToContainerAsync(nodeInfo.Guid, nodeInfo.ParentNodeGuid);
|
||||
if (isSuuccess)
|
||||
{
|
||||
loadSuuccessNodes.Add(nodeInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadFailureNodes.Add(nodeInfo);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
foreach (var f_node in loadFailureNodes)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"无法移动到指定容器的节点Guid :{f_node.Guid}" +
|
||||
$"{Environment.NewLine}容器节点Guid{f_node.ParentNodeGuid}{Environment.NewLine}" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建节点/区域/基础控件
|
||||
/// </summary>
|
||||
/// <param name="nodeType">节点/区域/基础控件类型</param>
|
||||
/// <param name="position">节点在画布上的位置(</param>
|
||||
/// <param name="methodDetailsInfo">节点绑定的方法说明</param>
|
||||
public async Task<NodeInfo> CreateNodeAsync(NodeControlType nodeControlType,
|
||||
PositionOfUI position,
|
||||
MethodDetailsInfo methodDetailsInfo = null)
|
||||
{
|
||||
IsLoadingNode = true;
|
||||
var nodeInfo = await msgClient.SendAndWaitDataAsync<NodeInfo>(EnvMsgTheme.CreateNode, new
|
||||
{
|
||||
nodeType = nodeControlType.ToString(),
|
||||
position = position,
|
||||
mdInfo = methodDetailsInfo,
|
||||
});
|
||||
|
||||
MethodDetails? methodDetails = null;
|
||||
if (!string.IsNullOrEmpty(nodeInfo.MethodName))
|
||||
{
|
||||
MethodDetailss.TryGetValue(nodeInfo.MethodName, out methodDetails);// 加载远程环境时尝试获取方法信息
|
||||
}
|
||||
|
||||
//MethodDetailss.TryGetValue(methodDetailsInfo.MethodName, out var methodDetails);// 加载项目时尝试获取方法信息
|
||||
var nodeModel = FlowFunc.CreateNode(this, nodeControlType, methodDetails); // 远程环境下加载节点
|
||||
nodeModel.LoadInfo(nodeInfo);
|
||||
TryAddNode(nodeModel);
|
||||
IsLoadingNode = false;
|
||||
|
||||
// 通知UI更改
|
||||
UIContextOperation.Invoke(() =>
|
||||
{
|
||||
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, position));
|
||||
});
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将节点放置在容器中
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid)
|
||||
{
|
||||
var isSuuccess = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.PlaceNode, new
|
||||
{
|
||||
nodeGuid = nodeGuid,
|
||||
containerNodeGuid = containerNodeGuid,
|
||||
});
|
||||
if (isSuuccess)
|
||||
{
|
||||
OnNodePlace?.Invoke(new NodePlaceEventArgs(nodeGuid, containerNodeGuid)); // 通知UI更改节点放置位置
|
||||
}
|
||||
return isSuuccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将节点从容器中脱离
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> TakeOutNodeToContainerAsync(string nodeGuid)
|
||||
{
|
||||
var isSuuccess = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.TakeOutNode, new
|
||||
{
|
||||
nodeGuid = nodeGuid,
|
||||
});
|
||||
if (isSuuccess)
|
||||
{
|
||||
OnNodeTakeOut?.Invoke(new NodeTakeOutEventArgs(nodeGuid)); // 重新放置在画布上
|
||||
}
|
||||
return isSuuccess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 移除远程环境的某个节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> RemoveNodeAsync(string nodeGuid)
|
||||
{
|
||||
var result = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.RemoveNode, new
|
||||
{
|
||||
nodeGuid
|
||||
});
|
||||
if (result)
|
||||
{
|
||||
UIContextOperation.Invoke(() =>
|
||||
{
|
||||
OnNodeRemove?.Invoke(new NodeRemoveEventArgs(nodeGuid));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.WriteLine(InfoType.ERROR, "删除失败");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激活远程某个全局触发器节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public void ActivateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
// 需要重写
|
||||
_ = msgClient.SendAsync(EnvMsgTheme.ActivateFlipflopNode, new
|
||||
{
|
||||
nodeGuid
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停远程某个全局触发器节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public void TerminateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
// 需要重写
|
||||
_ = msgClient.SendAsync(EnvMsgTheme.TerminateFlipflopNode, new
|
||||
{
|
||||
nodeGuid
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置远程环境某个节点的中断
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="isInterrupt"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> SetNodeInterruptAsync(string nodeGuid, bool isInterrupt)
|
||||
{
|
||||
var state = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.SetNodeInterrupt, // 设置节点中断
|
||||
new
|
||||
{
|
||||
nodeGuid,
|
||||
isInterrupt,
|
||||
});
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为远程某个节点添加中断的表达式
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="expression"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> AddInterruptExpressionAsync(string key, string expression)
|
||||
{
|
||||
var state = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.AddInterruptExpression, // 设置节点/对象的中断表达式
|
||||
new
|
||||
{
|
||||
key,
|
||||
expression,
|
||||
});
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查并获取节点/对象是否正在监视、以及监视的表达式(需要重写)
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<(bool, string[])> CheckObjMonitorStateAsync(string key)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
var exps = Array.Empty<string>();
|
||||
return (false, exps);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await msgClient.SendAndWaitDataAsync<(bool, string[])>(EnvMsgTheme.SetNodeInterrupt, // 检查并获取节点/对象是否正在监视、以及监视的表达式
|
||||
new
|
||||
{
|
||||
key,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 需要定位某个节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public void NodeLocated(string nodeGuid)
|
||||
{
|
||||
UIContextOperation?.Invoke(() => OnNodeLocated?.Invoke(new NodeLocatedEventArgs(nodeGuid)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通知远程环境修改节点数据
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public async Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
|
||||
{
|
||||
if(IsLoadingProject || IsLoadingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//this.WriteLine(InfoType.INFO, $"通知远程环境修改节点数据:{nodeGuid},name:{path},value:{value}");
|
||||
await msgClient.SendAsync(EnvMsgTheme.ValueNotification, new
|
||||
{
|
||||
nodeGuid = nodeGuid,
|
||||
path = path,
|
||||
value = value.ToString(),
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 改变可选参数的数目
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">对应的节点Guid</param>
|
||||
/// <param name="isAdd">true,增加参数;false,减少参数</param>
|
||||
/// <param name="paramIndex">以哪个参数为模板进行拷贝,或删去某个参数(该参数必须为可选参数)</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ChangeParameter(string nodeGuid, bool isAdd, int paramIndex)
|
||||
{
|
||||
if (IsLoadingProject || IsLoadingNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!NodeModels.TryGetValue(nodeGuid,out var nodeModel))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//this.WriteLine(InfoType.INFO, $"通知远程环境修改节点可选数据:{nodeGuid},isAdd:{isAdd},paramIndex:{paramIndex}");
|
||||
var result = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.ChangeParameter, new
|
||||
{
|
||||
nodeGuid = nodeGuid,
|
||||
isAdd = isAdd,
|
||||
paramIndex = paramIndex,
|
||||
});
|
||||
if (result) {
|
||||
if (isAdd)
|
||||
{
|
||||
nodeModel.MethodDetails.AddParamsArg(paramIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeModel.MethodDetails.RemoveParamsArg(paramIndex);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region 私有方法
|
||||
|
||||
|
||||
private bool TryAddNode(NodeModelBase nodeModel)
|
||||
{
|
||||
NodeModels[nodeModel.Guid] = nodeModel;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 私有方法,通过节点信息集合加载节点
|
||||
/// </summary>
|
||||
/// <param name="nodeInfos"></param>
|
||||
private void LoadNodeInfos(List<NodeInfo> nodeInfos)
|
||||
{
|
||||
#region 从NodeInfo创建NodeModel
|
||||
foreach (NodeInfo? nodeInfo in nodeInfos)
|
||||
{
|
||||
@@ -709,27 +1072,32 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
nodeModel.LoadInfo(nodeInfo); // 创建节点model
|
||||
TryAddNode(nodeModel); // 加载项目时将节点加载到环境中
|
||||
if (!string.IsNullOrEmpty(nodeInfo.ParentNodeGuid) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var parentNode))
|
||||
{
|
||||
needPlaceNodeInfos.Add(nodeInfo); // 需要重新放置的节点
|
||||
}
|
||||
|
||||
UIContextOperation?.Invoke(() =>
|
||||
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position))); // 添加到UI上
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 重新放置节点
|
||||
List<NodeInfo> needPlaceNodeInfos = [];
|
||||
foreach (NodeInfo? nodeInfo in nodeInfos)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(nodeInfo.ParentNodeGuid) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var parentNode))
|
||||
{
|
||||
needPlaceNodeInfos.Add(nodeInfo); // 需要重新放置的节点
|
||||
}
|
||||
}
|
||||
foreach (NodeInfo nodeInfo in needPlaceNodeInfos)
|
||||
{
|
||||
if (NodeModels.TryGetValue(nodeInfo.Guid, out var childNode) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var parentNode))
|
||||
{
|
||||
childNode.ParentNode = parentNode;
|
||||
childNode.ContainerNode = parentNode;
|
||||
parentNode.ChildrenNode.Add(childNode);
|
||||
UIContextOperation?.Invoke(() => OnNodeParentChildChange?.Invoke(
|
||||
new NodeContainerChildChangeEventArgs(childNode.Guid, parentNode.Guid,
|
||||
NodeContainerChildChangeEventArgs.Type.Place)));
|
||||
UIContextOperation?.Invoke(() =>
|
||||
OnNodePlace?.Invoke(new NodePlaceEventArgs(nodeInfo.Guid, nodeInfo.ParentNodeGuid)) // 通知UI更改节点放置位置
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -805,141 +1173,23 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 创建节点/区域/基础控件
|
||||
/// </summary>
|
||||
/// <param name="nodeType">节点/区域/基础控件类型</param>
|
||||
/// <param name="position">节点在画布上的位置(</param>
|
||||
/// <param name="methodDetailsInfo">节点绑定的方法说明</param>
|
||||
public async Task<NodeInfo> CreateNodeAsync(NodeControlType nodeControlType, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null)
|
||||
{
|
||||
IsLoadingNode = true;
|
||||
var nodeInfo = await msgClient.SendAndWaitDataAsync<NodeInfo>(EnvMsgTheme.CreateNode, new
|
||||
{
|
||||
nodeType = nodeControlType.ToString(),
|
||||
position = position,
|
||||
mdInfo = methodDetailsInfo,
|
||||
});
|
||||
|
||||
MethodDetails? methodDetails = null;
|
||||
if (!string.IsNullOrEmpty(nodeInfo.MethodName))
|
||||
{
|
||||
MethodDetailss.TryGetValue(nodeInfo.MethodName, out methodDetails);// 加载远程环境时尝试获取方法信息
|
||||
}
|
||||
#region 远程环境下暂未实现的接口
|
||||
|
||||
//MethodDetailss.TryGetValue(methodDetailsInfo.MethodName, out var methodDetails);// 加载项目时尝试获取方法信息
|
||||
var nodeModel = FlowFunc.CreateNode(this, nodeControlType, methodDetails); // 远程环境下加载节点
|
||||
nodeModel.LoadInfo(nodeInfo);
|
||||
TryAddNode(nodeModel);
|
||||
IsLoadingNode = false;
|
||||
|
||||
// 通知UI更改
|
||||
UIContextOperation.Invoke(() =>
|
||||
{
|
||||
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, position));
|
||||
});
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将节点放置在容器中/从容器中取出
|
||||
/// </summary>
|
||||
/// <param name="childNodeGuid">子节点(主要节点)</param>
|
||||
/// <param name="parentNodeGuid">父节点</param>
|
||||
/// <param name="isPlace">是否组合(反之为分解节点组合关系)</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ChangeNodeContainerChild(string childNodeGuid, string parentNodeGuid, bool isAssembly)
|
||||
{
|
||||
this.WriteLine(InfoType.WARN, "远程环境尚未实现的接口(重要,会尽快实现):ChangeNodeParentChild");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> RemoveNodeAsync(string nodeGuid)
|
||||
{
|
||||
var result = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.RemoveNode, new
|
||||
{
|
||||
nodeGuid
|
||||
});
|
||||
if (result)
|
||||
{
|
||||
UIContextOperation.Invoke(() =>
|
||||
{
|
||||
OnNodeRemove?.Invoke(new NodeRemoveEventArgs(nodeGuid));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.WriteLine(InfoType.ERROR, "删除失败");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void ActivateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
_ = msgClient.SendAsync(EnvMsgTheme.ActivateFlipflopNode, new
|
||||
{
|
||||
nodeGuid
|
||||
});
|
||||
}
|
||||
|
||||
public void TerminateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
_ = msgClient.SendAsync(EnvMsgTheme.TerminateFlipflopNode, new
|
||||
{
|
||||
nodeGuid
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<bool> SetNodeInterruptAsync(string nodeGuid, bool isInterrupt)
|
||||
{
|
||||
var state = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.SetNodeInterrupt, // 设置节点中断
|
||||
new
|
||||
{
|
||||
nodeGuid,
|
||||
isInterrupt,
|
||||
});
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> AddInterruptExpressionAsync(string key, string expression)
|
||||
{
|
||||
var state = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.AddInterruptExpression, // 设置节点/对象的中断表达式
|
||||
new
|
||||
{
|
||||
key,
|
||||
expression,
|
||||
});
|
||||
return state;
|
||||
}
|
||||
|
||||
public void SetMonitorObjState(string key, bool isMonitor)
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:SetMonitorObjState");
|
||||
}
|
||||
|
||||
public async Task<(bool, string[])> CheckObjMonitorStateAsync(string key)
|
||||
public async Task<object> InvokeNodeAsync(IDynamicContext context, string nodeGuid)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
var exps = Array.Empty<string>();
|
||||
return (false, exps);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await msgClient.SendAndWaitDataAsync<(bool, string[])>(EnvMsgTheme.SetNodeInterrupt, // 检查并获取节点/对象是否正在监视、以及监视的表达式
|
||||
new
|
||||
{
|
||||
key,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
// 登录到远程环境后,启动器相关方法无效
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现接口 InvokeNodeAsync");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public async Task<ChannelFlowInterrupt.CancelType> GetOrCreateGlobalInterruptAsync()
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:GetOrCreateGlobalInterruptAsync");
|
||||
@@ -961,76 +1211,31 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 对象监视表达式
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="monitorData"></param>
|
||||
/// <param name="sourceType"></param>
|
||||
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:MonitorObjectNotification");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发节点的中断
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="expression"></param>
|
||||
/// <param name="type"></param>
|
||||
public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type)
|
||||
{
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:TriggerInterrupt");
|
||||
}
|
||||
|
||||
public void NodeLocated(string nodeGuid)
|
||||
{
|
||||
UIContextOperation?.Invoke(() => OnNodeLocated?.Invoke(new NodeLocatedEventArgs(nodeGuid)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public async Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
|
||||
{
|
||||
if(IsLoadingProject || IsLoadingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//this.WriteLine(InfoType.INFO, $"通知远程环境修改节点数据:{nodeGuid},name:{path},value:{value}");
|
||||
_ = msgClient.SendAsync(EnvMsgTheme.ValueNotification, new
|
||||
{
|
||||
nodeGuid = nodeGuid,
|
||||
path = path,
|
||||
value = value.ToString(),
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 改变可选参数的数目
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">对应的节点Guid</param>
|
||||
/// <param name="isAdd">true,增加参数;false,减少参数</param>
|
||||
/// <param name="paramIndex">以哪个参数为模板进行拷贝,或删去某个参数(该参数必须为可选参数)</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ChangeParameter(string nodeGuid, bool isAdd, int paramIndex)
|
||||
{
|
||||
if (IsLoadingProject || IsLoadingNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!NodeModels.TryGetValue(nodeGuid,out var nodeModel))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//this.WriteLine(InfoType.INFO, $"通知远程环境修改节点可选数据:{nodeGuid},isAdd:{isAdd},paramIndex:{paramIndex}");
|
||||
var result = await msgClient.SendAndWaitDataAsync<bool>(EnvMsgTheme.ChangeParameter, new
|
||||
{
|
||||
nodeGuid = nodeGuid,
|
||||
isAdd = isAdd,
|
||||
paramIndex = paramIndex,
|
||||
});
|
||||
if (result) {
|
||||
if (isAdd)
|
||||
{
|
||||
nodeModel.MethodDetails.AddParamsArg(paramIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeModel.MethodDetails.RemoveParamsArg(paramIndex);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#region 流程依赖类库的接口
|
||||
|
||||
@@ -1081,5 +1286,9 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
catch (FlipflopException ex)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR,$"触发器[{singleFlipFlopNode.MethodDetails.MethodName}]因非预期异常终止。"+ex.Message);
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"触发器[{singleFlipFlopNode.MethodDetails.MethodName}]因非预期异常终止。"+ex.Message);
|
||||
if (ex.Type == FlipflopException.CancelClass.CancelFlow)
|
||||
{
|
||||
break;
|
||||
@@ -442,7 +442,7 @@ namespace Serein.NodeFlow
|
||||
catch (Exception ex)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"触发器[{singleFlipFlopNode.Guid}]异常。"+ ex.Message);
|
||||
//await Console.Out.WriteLineAsync(ex.Message);
|
||||
await Task.Delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,19 @@ namespace Serein.NodeFlow.Model
|
||||
|
||||
public void PlaceNode(NodeModelBase nodeModel)
|
||||
{
|
||||
_ = this.Env.RemoveNodeAsync(DataNode?.Guid);
|
||||
DataNode = nodeModel;
|
||||
// 全局数据节点只有一个子控件
|
||||
if (DataNode is not null)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await this.Env.RemoveNodeAsync(DataNode?.Guid);
|
||||
DataNode = nodeModel;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
DataNode = nodeModel;
|
||||
}
|
||||
}
|
||||
|
||||
public void TakeOutAll()
|
||||
|
||||
@@ -201,12 +201,15 @@ namespace Serein.NodeFlow.Tool
|
||||
|
||||
#region 功能性方法
|
||||
|
||||
private readonly string SereinLibraryDll = $"{nameof(Serein)}.{nameof(Serein.Library)}.dll";
|
||||
/// <summary>
|
||||
/// 基础依赖
|
||||
/// </summary>
|
||||
public readonly static string SereinBaseLibrary = $"{nameof(Serein)}.{nameof(Serein.Library)}.dll";
|
||||
|
||||
private (NodeLibraryInfo, List<MethodDetailsInfo>) LoadDllNodeInfo(string dllFilePath)
|
||||
{
|
||||
var fileName = Path.GetFileName(dllFilePath); // 获取文件名
|
||||
if (SereinLibraryDll.Equals(fileName))
|
||||
if (SereinBaseLibrary.Equals(fileName))
|
||||
{
|
||||
return LoadAssembly(typeof(IFlowEnvironment).Assembly, () => {
|
||||
//SereinEnv.PrintInfo(InfoType.WRAN, "基础模块不能卸载");
|
||||
@@ -215,9 +218,9 @@ namespace Serein.NodeFlow.Tool
|
||||
else
|
||||
{
|
||||
var dir = Path.GetDirectoryName(dllFilePath); // 获取目录路径
|
||||
var sereinFlowLibraryPath = Path.Combine(dir, SereinLibraryDll);
|
||||
var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary);
|
||||
// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
||||
var flowAlc = new FlowLibraryAssemblyContext(sereinFlowLibraryPath, fileName);
|
||||
var flowAlc = new FlowLibraryAssemblyContext(sereinFlowBaseLibraryPath, fileName);
|
||||
Action actionUnload = () =>
|
||||
{
|
||||
flowAlc?.Unload(); // 卸载程序集
|
||||
|
||||
Reference in New Issue
Block a user