diff --git a/Library/Api/IDynamicContext.cs b/Library/Api/IDynamicContext.cs index 96eb052..22d0344 100644 --- a/Library/Api/IDynamicContext.cs +++ b/Library/Api/IDynamicContext.cs @@ -60,33 +60,33 @@ namespace Serein.Library.Api /// /// 当前节点 /// 运行时上一节点 - void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode); + void SetPreviousNode(IFlowNode currentNodeModel, IFlowNode PreviousNode); /// /// 获取当前节点的运行时上一节点,用以流程中获取数据 /// /// /// - NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel); + IFlowNode GetPreviousNode(IFlowNode currentNodeModel); /// /// 获取节点的数据(当前节点需要获取上一节点数据时,需要从 运行时上一节点 的Guid 通过这个方法进行获取 /// /// /// - FlowResult GetFlowData(NodeModelBase nodeModel); + FlowResult GetFlowData(IFlowNode nodeModel); /// /// 上一节点数据透传到下一节点 /// /// - FlowResult TransmissionData(NodeModelBase nodeModel); + FlowResult TransmissionData(IFlowNode nodeModel); /// /// 添加或更新当前节点的数据 /// /// /// - void AddOrUpdate(NodeModelBase nodeModel, FlowResult flowData); + void AddOrUpdate(IFlowNode nodeModel, FlowResult flowData); /// /// 重置流程状态(用于对象池回收) diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index 6debb1e..a5d85c3 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -351,7 +351,7 @@ namespace Serein.Library.Api /// 画布 /// 节点对象 /// 位置 - public NodeCreateEventArgs(string canvasGuid, NodeModelBase nodeModel, PositionOfUI position) + public NodeCreateEventArgs(string canvasGuid, IFlowNode nodeModel, PositionOfUI position) { CanvasGuid = canvasGuid; this.NodeModel = nodeModel; @@ -365,7 +365,7 @@ namespace Serein.Library.Api /// /// 节点Model对象 /// - public NodeModelBase NodeModel { get; private set; } + public IFlowNode NodeModel { get; private set; } /// /// 在UI上的位置 /// @@ -1070,7 +1070,7 @@ namespace Serein.Library.Api /// /// /// - bool TryGetNodeModel(string nodeGuid, out NodeModelBase nodeModel); + bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel); /// /// 获取方法描述信息 diff --git a/Library/Api/IFlowNode.cs b/Library/Api/IFlowNode.cs new file mode 100644 index 0000000..0d4f829 --- /dev/null +++ b/Library/Api/IFlowNode.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Threading.Tasks; +using Serein.Library; + +namespace Serein.Library.Api +{ + + /// + /// 流程节点 + /// + public interface IFlowNode : INotifyPropertyChanged, IDynamicFlowNode + { + /// + /// 节点持有的运行环境 + /// + IFlowEnvironment Env { get; set; } + + /// + /// 节点唯一标识 + /// + string Guid { get; set; } + + /// + /// 节点的类型 + /// + NodeControlType ControlType { get; set; } + + /// + /// 节点所在画布 + /// + FlowCanvasDetails CanvasDetails { get; set; } + + /// + /// 节点位置 + /// + PositionOfUI Position { get; set; } + + /// + /// 节点显示名称 + /// + string DisplayName { get; set; } + + /// + /// 是否作为公开的节点,用以“流程接口”节点调用 + /// + bool IsPublic { get; set; } + + /// + /// 是否为基础节点,指示节点创建中的行为 + /// + bool IsBase { get; } + + /// + /// 最多可以放置几个节点,当该节点具有容器功能时,用来指示其容器的行为。 + /// + int MaxChildrenCount { get;} + + /// + /// 调试器 + /// + NodeDebugSetting DebugSetting { get; set; } + + /// + /// 节点方法描述,包含入参数据 + /// + MethodDetails MethodDetails { get; set; } + + /// + /// 父节点 + /// + Dictionary> PreviousNodes { get;} + /// + /// 子节点 + /// + Dictionary> SuccessorNodes { get; set; } + + /// + /// 当该节点放置在某个具有容器行为的节点时,该值指示其容器节点 + /// + IFlowNode ContainerNode { get; set; } + + /// + /// 当该节点具备容器行为时,该集合包含其容器中的节点 + /// + List ChildrenNode { get; } + + /// + /// 节点创建时的行为 + /// + void OnCreating(); + /// + /// 节点移除时的行为 + /// + void Remove(); + + /// + /// 节点保存时如若需要保存自定义数据,可通过该方法进行控制保存逻辑 + /// + /// + /// + NodeInfo SaveCustomData(NodeInfo nodeInfo); + + /// + /// 节点从信息创建后需要加载自定义数据时,可通过该方法进行控制加载逻辑 + /// + /// + void LoadCustomData(NodeInfo nodeInfo); + + /// + /// 节点执行方法 + /// + /// + /// + /// + Task ExecutingAsync(IDynamicContext context, CancellationToken token); + } +} diff --git a/Library/Api/INodeContainer.cs b/Library/Api/INodeContainer.cs index 777902d..cdd8198 100644 --- a/Library/Api/INodeContainer.cs +++ b/Library/Api/INodeContainer.cs @@ -15,13 +15,13 @@ namespace Serein.Library.Api /// 放置一个节点 /// /// - bool PlaceNode(NodeModelBase nodeModel); + bool PlaceNode(IFlowNode nodeModel); /// /// 取出一个节点 /// /// - bool TakeOutNode(NodeModelBase nodeModel); + bool TakeOutNode(IFlowNode nodeModel); /// /// 取出所有节点(用于删除容器) diff --git a/Library/Api/IScriptFlowApi.cs b/Library/Api/IScriptFlowApi.cs index c0dd0e8..dfcf197 100644 --- a/Library/Api/IScriptFlowApi.cs +++ b/Library/Api/IScriptFlowApi.cs @@ -18,7 +18,7 @@ namespace Serein.Library.Api /// /// 对应的节点 /// - NodeModelBase NodeModel { get; } + IFlowNode NodeModel { get; } /// /// 根据索引从入参数据获取数据 diff --git a/Library/Extension/FlowModelExtension.cs b/Library/Extension/FlowModelExtension.cs index a83001a..4e8a8d3 100644 --- a/Library/Extension/FlowModelExtension.cs +++ b/Library/Extension/FlowModelExtension.cs @@ -62,7 +62,7 @@ namespace Serein.Library /// 输出方法参数信息 /// /// - public static ParameterData[] SaveParameterInfo(this NodeModelBase nodeModel) + public static ParameterData[] SaveParameterInfo(this IFlowNode nodeModel) { if (nodeModel.MethodDetails is null || nodeModel.MethodDetails.ParameterDetailss == null) { @@ -93,7 +93,7 @@ namespace Serein.Library /// 导出为节点信息 /// /// - public static NodeInfo ToInfo(this NodeModelBase nodeModel) + public static NodeInfo ToInfo(this IFlowNode nodeModel) { // if (MethodDetails == null) return null; var trueNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsSucceed].Select(item => item.Guid); // 真分支 @@ -137,7 +137,7 @@ namespace Serein.Library /// /// /// - public static void LoadInfo(this NodeModelBase nodeModel, NodeInfo nodeInfo) + public static void LoadInfo(this IFlowNode nodeModel, NodeInfo nodeInfo) { nodeModel.Guid = nodeInfo.Guid; nodeModel.Position = nodeInfo.Position ?? new PositionOfUI(0, 0);// 加载位置信息 @@ -200,10 +200,10 @@ namespace Serein.Library /// /// 流程运行 /// - public static async Task StartFlowAsync(this NodeModelBase nodeModel, IDynamicContext context, CancellationToken token) + public static async Task StartFlowAsync(this IFlowNode nodeModel, IDynamicContext context, CancellationToken token) { - Stack stack = new Stack(); - HashSet processedNodes = new HashSet(); // 用于记录已处理上游节点的节点 + Stack stack = new Stack(); + HashSet processedNodes = new HashSet(); // 用于记录已处理上游节点的节点 stack.Push(nodeModel); while (context.RunState != RunState.Completion // 没有完成 && token.IsCancellationRequested == false // 没有取消 @@ -276,7 +276,7 @@ namespace Serein.Library /// /// 获取对应的参数数组 /// - public static async Task GetParametersAsync(this NodeModelBase nodeModel, IDynamicContext context, CancellationToken token) + public static async Task GetParametersAsync(this IFlowNode nodeModel, IDynamicContext context, CancellationToken token) { if (nodeModel.MethodDetails.ParameterDetailss.Length == 0) { @@ -412,7 +412,7 @@ namespace Serein.Library /// /// 不再中断 /// - public static void CancelInterrupt(NodeModelBase nodeModel) + public static void CancelInterrupt(IFlowNode nodeModel) { nodeModel.DebugSetting.IsInterrupt = false; nodeModel.DebugSetting.CancelInterrupt?.Invoke(); @@ -424,7 +424,7 @@ namespace Serein.Library /// /// 节点Model /// 新的方法描述 - public static void UploadMethod(this NodeModelBase nodeModel, MethodDetails newMd) + public static void UploadMethod(this IFlowNode nodeModel, MethodDetails newMd) { var thisMd = nodeModel.MethodDetails; diff --git a/Library/FlowNode/DynamicContext.cs b/Library/FlowNode/DynamicContext.cs index c2223f8..24869c6 100644 --- a/Library/FlowNode/DynamicContext.cs +++ b/Library/FlowNode/DynamicContext.cs @@ -49,24 +49,24 @@ namespace Serein.Library /// /// 每个流程上下文分别存放节点的当前数据 /// - private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary(); + private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary(); /// /// 每个流程上下文存储运行时节点的调用关系 /// - private readonly ConcurrentDictionary dictPreviousNodes = new ConcurrentDictionary(); + private readonly ConcurrentDictionary dictPreviousNodes = new ConcurrentDictionary(); /// /// 记录忽略处理的流程 /// - private readonly ConcurrentDictionary dictIgnoreNodeFlow = new ConcurrentDictionary(); + private readonly ConcurrentDictionary dictIgnoreNodeFlow = new ConcurrentDictionary(); /// /// 设置运行时上一节点 /// /// 当前节点 /// 上一节点 - public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode) + public void SetPreviousNode(IFlowNode currentNodeModel, IFlowNode PreviousNode) { dictPreviousNodes.AddOrUpdate(currentNodeModel, (_) => PreviousNode, (o, n) => PreviousNode); } @@ -75,7 +75,7 @@ namespace Serein.Library /// 忽略处理该节点流程 /// /// - public void IgnoreFlowHandle(NodeModelBase node) + public void IgnoreFlowHandle(IFlowNode node) { dictIgnoreNodeFlow.AddOrUpdate(node, (o) => true, (o, n) => true); } @@ -85,7 +85,7 @@ namespace Serein.Library /// /// /// - public bool GetIgnodeFlowStateUpload(NodeModelBase node) + public bool GetIgnodeFlowStateUpload(IFlowNode node) { return dictIgnoreNodeFlow.TryGetValue(node, out var state) ? state : false; } @@ -94,7 +94,7 @@ namespace Serein.Library /// /// /// - public void RecoverIgnodeFlowStateUpload(NodeModelBase node) + public void RecoverIgnodeFlowStateUpload(IFlowNode node) { dictIgnoreNodeFlow.AddOrUpdate(node, (o) => false, (o, n) => false); } @@ -105,7 +105,7 @@ namespace Serein.Library /// /// /// - public NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel) + public IFlowNode GetPreviousNode(IFlowNode currentNodeModel) { if (dictPreviousNodes.TryGetValue(currentNodeModel, out var node)) { @@ -122,7 +122,7 @@ namespace Serein.Library /// /// 节点 /// - public FlowResult GetFlowData(NodeModelBase nodeGuid) + public FlowResult GetFlowData(IFlowNode nodeGuid) { if (dictNodeFlowData.TryGetValue(nodeGuid, out var data)) { @@ -139,7 +139,7 @@ namespace Serein.Library /// /// 节点 /// 新的数据 - public void AddOrUpdate(NodeModelBase nodeModel, FlowResult flowData) + public void AddOrUpdate(IFlowNode nodeModel, FlowResult flowData) { // this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData); dictNodeFlowData.AddOrUpdate(nodeModel, _ => flowData, (o,n ) => flowData); @@ -149,7 +149,7 @@ namespace Serein.Library /// 上一节点数据透传到下一节点 /// /// - public FlowResult TransmissionData(NodeModelBase nodeModel) + public FlowResult TransmissionData(IFlowNode nodeModel) { if (dictPreviousNodes.TryGetValue(nodeModel, out var previousNode)) // 首先获取当前节点的上一节点 { diff --git a/Library/FlowNode/FlowCanvasDetails.cs b/Library/FlowNode/FlowCanvasDetails.cs index 6725cfa..79440a5 100644 --- a/Library/FlowNode/FlowCanvasDetails.cs +++ b/Library/FlowNode/FlowCanvasDetails.cs @@ -30,13 +30,13 @@ namespace Serein.Library /// 画布拥有的节点 /// [PropertyInfo(IsProtection = true)] - private System.Collections.ObjectModel.ObservableCollection _nodes = []; + private System.Collections.ObjectModel.ObservableCollection _nodes = []; /// /// 画布公开的节点 /// [PropertyInfo(IsProtection = true)] - private System.Collections.ObjectModel.ObservableCollection _publicNodes = []; + private System.Collections.ObjectModel.ObservableCollection _publicNodes = []; /// /// 标识画布ID @@ -90,7 +90,7 @@ namespace Serein.Library /// 起始节点 /// [PropertyInfo] - private NodeModelBase _startNode; + private IFlowNode _startNode; } diff --git a/Library/FlowNode/FlowResult.cs b/Library/FlowNode/FlowResult.cs index 350c756..d847ae6 100644 --- a/Library/FlowNode/FlowResult.cs +++ b/Library/FlowNode/FlowResult.cs @@ -30,7 +30,7 @@ namespace Serein.Library /// /// /// - public FlowResult(NodeModelBase nodeModel, IDynamicContext context, object value) + public FlowResult(IFlowNode nodeModel, IDynamicContext context, object value) { this.NodeGuid = nodeModel.Guid; this.ContextGuid = context.Guid; @@ -41,7 +41,7 @@ namespace Serein.Library /// /// /// - public FlowResult(NodeModelBase nodeModel, IDynamicContext context) + public FlowResult(IFlowNode nodeModel, IDynamicContext context) { this.NodeGuid = nodeModel.Guid; this.ContextGuid = context.Guid; diff --git a/Library/FlowNode/JunctionModel.cs b/Library/FlowNode/JunctionModel.cs index 6fbf28e..2abede1 100644 --- a/Library/FlowNode/JunctionModel.cs +++ b/Library/FlowNode/JunctionModel.cs @@ -1,4 +1,5 @@ -using System; +using Serein.Library.Api; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -32,7 +33,7 @@ namespace Serein.Library.FlowNode /// public class JunctionModel { - public JunctionModel(NodeModelBase NodeModel, JunctionType JunctionType) + public JunctionModel(IFlowNode NodeModel, JunctionType JunctionType) { Guid = System.Guid.NewGuid().ToString(); this.NodeModel = NodeModel; @@ -51,6 +52,6 @@ namespace Serein.Library.FlowNode /// /// 连接点依附的节点 /// - public NodeModelBase NodeModel { get; } + public IFlowNode NodeModel { get; } } } diff --git a/Library/FlowNode/MethodDetails.cs b/Library/FlowNode/MethodDetails.cs index ee07104..8aefd42 100644 --- a/Library/FlowNode/MethodDetails.cs +++ b/Library/FlowNode/MethodDetails.cs @@ -21,7 +21,7 @@ namespace Serein.Library /// 对应的节点 /// [PropertyInfo(IsProtection = true)] - private NodeModelBase _nodeModel; + private IFlowNode _nodeModel; /// /// 对应的程序集 @@ -179,7 +179,7 @@ namespace Serein.Library /// 生成元数据 /// /// 标识属于哪个节点 - public MethodDetails(NodeModelBase nodeModel) + public MethodDetails(IFlowNode nodeModel) { NodeModel = nodeModel; } @@ -226,10 +226,10 @@ namespace Serein.Library /// 从DLL拖动出来时,从元数据拷贝新的实例,作为属于节点独享的方法描述 /// /// - public MethodDetails CloneOfNode( NodeModelBase nodeModel) + public MethodDetails CloneOfNode( IFlowNode nodeModel) { // this => 是元数据 - var md = new MethodDetails( nodeModel) // 创建新节点时拷贝实例 + var md = new MethodDetails(nodeModel) // 创建新节点时拷贝实例 { AssemblyName = this.AssemblyName, // 拷贝 //ActingInstance = this.ActingInstance, diff --git a/Library/FlowNode/NodeDebugSetting.cs b/Library/FlowNode/NodeDebugSetting.cs index 9743719..d556ab3 100644 --- a/Library/FlowNode/NodeDebugSetting.cs +++ b/Library/FlowNode/NodeDebugSetting.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json.Linq; +using Serein.Library.Api; using Serein.Library.Utils; using System; using System.Collections.Generic; @@ -17,7 +18,7 @@ namespace Serein.Library /// 创建属于某个节点的调试设置 /// /// - public NodeDebugSetting(NodeModelBase nodeModel) + public NodeDebugSetting(IFlowNode nodeModel) { NodeModel = nodeModel; } @@ -33,7 +34,7 @@ namespace Serein.Library /// 对应的节点 /// [PropertyInfo(IsProtection = true)] - private NodeModelBase _nodeModel; + private IFlowNode _nodeModel; /// /// 是否使能 diff --git a/Library/FlowNode/NodeModelBaseFunc.cs b/Library/FlowNode/NodeModelBaseFunc.cs index d807cf9..a66e38a 100644 --- a/Library/FlowNode/NodeModelBaseFunc.cs +++ b/Library/FlowNode/NodeModelBaseFunc.cs @@ -22,6 +22,9 @@ namespace Serein.Library + + + /// /// 节点基类 /// @@ -141,7 +144,6 @@ namespace Serein.Library } - } diff --git a/Library/FlowNode/ParameterDetails.cs b/Library/FlowNode/ParameterDetails.cs index c6e1f37..c7864b2 100644 --- a/Library/FlowNode/ParameterDetails.cs +++ b/Library/FlowNode/ParameterDetails.cs @@ -26,7 +26,7 @@ namespace Serein.Library /// 所在的节点 /// [PropertyInfo(IsProtection = true)] - private NodeModelBase _nodeModel; + private IFlowNode _nodeModel; /// /// 参数索引 @@ -130,7 +130,7 @@ namespace Serein.Library /// /// 为节点实例化新的入参描述 /// - public ParameterDetails(NodeModelBase nodeModel) + public ParameterDetails(IFlowNode nodeModel) { this.NodeModel = nodeModel; } @@ -185,7 +185,7 @@ namespace Serein.Library /// /// 对应的节点 /// - public ParameterDetails CloneOfModel(NodeModelBase nodeModel) + public ParameterDetails CloneOfModel(IFlowNode nodeModel) { var pd = new ParameterDetails(nodeModel) { @@ -224,7 +224,7 @@ namespace Serein.Library return context; } // 返回流程上下文 - if (typeof(NodeModelBase).IsAssignableFrom(DataType)) + if (typeof(IFlowNode).IsAssignableFrom(DataType)) { return NodeModel; } diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj index 761a9f1..f8baeb8 100644 --- a/Library/Serein.Library.csproj +++ b/Library/Serein.Library.csproj @@ -38,6 +38,8 @@ + + diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index 30d5fe8..8e1075a 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -301,7 +301,7 @@ namespace Serein.NodeFlow.Env /// 环境加载的节点集合 /// Node Guid - Node Model /// - private Dictionary NodeModels { get; } = []; + private Dictionary NodeModels { get; } = []; /// /// 运行环境加载的画布集合 @@ -746,7 +746,7 @@ namespace Serein.NodeFlow.Env sb.AppendLine(); for (int i = 0; i < groupedNodes.Length; i++) { - NodeModelBase? node = groupedNodes[i]; + IFlowNode? node = groupedNodes[i]; sb.AppendLine($"{i} => {node.Guid}"); } SereinEnv.WriteLine(InfoType.ERROR, $"无法卸载[{assemblyName}]程序集,因为这些节点依赖于此程序集:{sb.ToString()}"); @@ -1047,7 +1047,7 @@ namespace Serein.NodeFlow.Env { return Task.FromResult(null); } - NodeModelBase? nodeModel; + IFlowNode? nodeModel; if (methodDetailsInfo is null || string.IsNullOrEmpty(methodDetailsInfo.AssemblyName) || string.IsNullOrEmpty(methodDetailsInfo.MethodName)) @@ -1097,7 +1097,7 @@ namespace Serein.NodeFlow.Env } if (nodeModel.ContainerNode is INodeContainer tmpContainer) { - SereinEnv.WriteLine(InfoType.WARN, $"节点放置失败,节点[{nodeGuid}]已经放置于容器节点[{((NodeModelBase)tmpContainer).Guid}]"); + SereinEnv.WriteLine(InfoType.WARN, $"节点放置失败,节点[{nodeGuid}]已经放置于容器节点[{((IFlowNode)tmpContainer).Guid}]"); return Task.FromResult(false); } @@ -1183,7 +1183,7 @@ namespace Serein.NodeFlow.Env var pCType = pnc.Key; // 连接类型 for (int i = 0; i < pnc.Value.Count; i++) { - NodeModelBase? pNode = pnc.Value[i]; + IFlowNode? pNode = pnc.Value[i]; pNode.SuccessorNodes[pCType].Remove(remoteNode); UIContextOperation?.Invoke(() => OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs( @@ -1210,7 +1210,7 @@ namespace Serein.NodeFlow.Env var connectionType = snc.Key; // 连接类型 for (int i = 0; i < snc.Value.Count; i++) { - NodeModelBase? toNode = snc.Value[i]; + IFlowNode? toNode = snc.Value[i]; await RemoteConnectAsync(canvasGuid, remoteNode, toNode, connectionType); @@ -1605,7 +1605,7 @@ namespace Serein.NodeFlow.Env /// 节点Guid /// 节点Model /// 无法获取节点、Guid/节点为null时报错 - public bool TryGetNodeModel(string nodeGuid,out NodeModelBase nodeModel) + public bool TryGetNodeModel(string nodeGuid,out IFlowNode nodeModel) { if (string.IsNullOrEmpty(nodeGuid)) { @@ -1793,7 +1793,7 @@ namespace Serein.NodeFlow.Env /// 目标节点Model /// 连接关系 /// - private async Task RemoteConnectAsync(string canvasGuid, NodeModelBase fromNode, NodeModelBase toNode, ConnectionInvokeType connectionType) + private async Task RemoteConnectAsync(string canvasGuid, IFlowNode fromNode, IFlowNode toNode, ConnectionInvokeType connectionType) { if (!FlowCanvass.ContainsKey(canvasGuid)) { @@ -1823,7 +1823,7 @@ namespace Serein.NodeFlow.Env /// 目标节点Model /// 连接关系 /// - private async Task RemoteConnectAsync(string canvasGuid, NodeModelBase fromNode, NodeModelBase toNode, int argIndex) + private async Task RemoteConnectAsync(string canvasGuid, IFlowNode fromNode, IFlowNode toNode, int argIndex) { if (!FlowCanvass.ContainsKey(canvasGuid)) { @@ -1856,7 +1856,7 @@ namespace Serein.NodeFlow.Env /// 创建节点 /// /// - private bool TryAddNode(NodeModelBase nodeModel) + private bool TryAddNode(IFlowNode nodeModel) { nodeModel.Guid ??= Guid.NewGuid().ToString(); NodeModels.TryAdd(nodeModel.Guid, nodeModel); @@ -1882,8 +1882,8 @@ namespace Serein.NodeFlow.Env /// 发起连接节点的控制点类型 /// 被连接节点的控制点类型 /// - public static (JunctionOfConnectionType,bool) CheckConnect(NodeModelBase fromNode, - NodeModelBase toNode, + public static (JunctionOfConnectionType,bool) CheckConnect(IFlowNode fromNode, + IFlowNode toNode, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType) { @@ -1947,7 +1947,7 @@ namespace Serein.NodeFlow.Env /// 起始节点 /// 目标节点 /// 连接关系 - private bool ConnectInvokeOfNode(string canvasGuid, NodeModelBase fromNode, NodeModelBase toNode, ConnectionInvokeType invokeType) + private bool ConnectInvokeOfNode(string canvasGuid, IFlowNode fromNode, IFlowNode toNode, ConnectionInvokeType invokeType) { if (fromNode.ControlType == NodeControlType.FlowCall) { @@ -2065,8 +2065,8 @@ namespace Serein.NodeFlow.Env /// /// private async Task ConnectArgSourceOfNodeAsync(string canvasGuid, - NodeModelBase fromNode, - NodeModelBase toNode, + IFlowNode fromNode, + IFlowNode toNode, ConnectionArgSourceType connectionArgSourceType, int argIndex) { @@ -2127,7 +2127,7 @@ namespace Serein.NodeFlow.Env /// /// 节点所在的画布 /// 起始节点 - private void SetStartNode(FlowCanvasDetails cavnasModel, NodeModelBase newStartNode) + private void SetStartNode(FlowCanvasDetails cavnasModel, IFlowNode newStartNode) { var oldNodeGuid = cavnasModel.StartNode?.Guid; /*if(TryGetNodeModel(oldNodeGuid, out var newStartNodeModel)) diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs index 4d6493f..b73c78c 100644 --- a/NodeFlow/Env/FlowEnvironmentDecorator.cs +++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs @@ -560,7 +560,7 @@ namespace Serein.NodeFlow.Env currentFlowEnvironment.SetUIContextOperation(uiContextOperation); } - public bool TryGetNodeModel(string nodeGuid, out NodeModelBase nodeModel) + public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel) { return currentFlowEnvironment.TryGetNodeModel(nodeGuid, out nodeModel); } diff --git a/NodeFlow/Env/RemoteFlowEnvironment.cs b/NodeFlow/Env/RemoteFlowEnvironment.cs index 88ada4d..a7a2c28 100644 --- a/NodeFlow/Env/RemoteFlowEnvironment.cs +++ b/NodeFlow/Env/RemoteFlowEnvironment.cs @@ -41,7 +41,7 @@ namespace Serein.NodeFlow.Env /// 环境加载的节点集合 /// Node Guid - Node Model /// - private Dictionary NodeModels { get; } = []; + private Dictionary NodeModels { get; } = []; public event LoadDllHandler OnDllLoad; public event ProjectLoadedHandler OnProjectLoaded; @@ -1167,21 +1167,21 @@ namespace Serein.NodeFlow.Env #region 私有方法 - private NodeModelBase? GuidToModel(string nodeGuid) + private IFlowNode? GuidToModel(string nodeGuid) { if (string.IsNullOrEmpty(nodeGuid)) { //throw new ArgumentNullException("not contains - Guid没有对应节点:" + (nodeGuid)); return null; } - if (!NodeModels.TryGetValue(nodeGuid, out NodeModelBase? nodeModel) || nodeModel is null) + if (!NodeModels.TryGetValue(nodeGuid, out IFlowNode? nodeModel) || nodeModel is null) { //throw new ArgumentNullException("null - Guid存在对应节点,但节点为null:" + (nodeGuid)); return null; } return nodeModel; } - private bool TryAddNode(NodeModelBase nodeModel) + private bool TryAddNode(IFlowNode nodeModel) { NodeModels[nodeModel.Guid] = nodeModel; return true; @@ -1268,7 +1268,7 @@ namespace Serein.NodeFlow.Env #region 确定节点之间的方法调用关系 foreach (var nodeInfo in nodeInfos) { - if (!NodeModels.TryGetValue(nodeInfo.Guid, out NodeModelBase? fromNode)) + if (!NodeModels.TryGetValue(nodeInfo.Guid, out IFlowNode? fromNode)) { // 不存在对应的起始节点 continue; @@ -1279,13 +1279,13 @@ namespace Serein.NodeFlow.Env (ConnectionInvokeType.IsError, nodeInfo.ErrorNodes), (ConnectionInvokeType.Upstream, nodeInfo.UpstreamNodes)]; - List<(ConnectionInvokeType, NodeModelBase[])> fromNodes = allToNodes.Where(info => info.guids.Length > 0) + List<(ConnectionInvokeType, IFlowNode[])> fromNodes = allToNodes.Where(info => info.guids.Length > 0) .Select(info => (info.connectionType, info.guids.Where(guid => NodeModels.ContainsKey(guid)).Select(guid => NodeModels[guid]) .ToArray())) .ToList(); // 遍历每种类型的节点分支(四种) - foreach ((ConnectionInvokeType connectionType, NodeModelBase[] toNodes) item in fromNodes) + foreach ((ConnectionInvokeType connectionType, IFlowNode[] toNodes) item in fromNodes) { // 遍历当前类型分支的节点(确认连接关系) foreach (var toNode in item.toNodes) @@ -1346,7 +1346,7 @@ namespace Serein.NodeFlow.Env } - public bool TryGetNodeModel(string nodeGuid, out NodeModelBase nodeModel) + public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel) { this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:TryGetNodeModel"); nodeModel = null; diff --git a/NodeFlow/FlowNodeExtension.cs b/NodeFlow/FlowNodeExtension.cs index 8056b78..21e3212 100644 --- a/NodeFlow/FlowNodeExtension.cs +++ b/NodeFlow/FlowNodeExtension.cs @@ -38,7 +38,7 @@ namespace Serein.NodeFlow /// 方法描述 /// /// - public static NodeModelBase CreateNode(IFlowEnvironment env, NodeControlType nodeControlType, + public static IFlowNode CreateNode(IFlowEnvironment env, NodeControlType nodeControlType, MethodDetails? methodDetails = null) { @@ -51,7 +51,7 @@ namespace Serein.NodeFlow // 生成实例 var nodeObj = Activator.CreateInstance(nodeMVVM.ModelType, env); - if (nodeObj is not NodeModelBase nodeModel) + if (nodeObj is not IFlowNode nodeModel) { throw new Exception($"无法创建目标节点类型的实例[{nodeControlType}]"); } diff --git a/NodeFlow/FlowWorkManagement.cs b/NodeFlow/FlowWorkManagement.cs index fe19718..0ca7dce 100644 --- a/NodeFlow/FlowWorkManagement.cs +++ b/NodeFlow/FlowWorkManagement.cs @@ -49,7 +49,7 @@ namespace Serein.NodeFlow public async Task RunAsync(CancellationToken token) { #region 注册所有节点所属的类的类型,如果注册失败则退出 - List nodes = new List(); + List nodes = new List(); foreach (var item in WorkOptions.Flows.Values) { var temp = item.GetNodes(); @@ -85,7 +85,7 @@ namespace Serein.NodeFlow var flowNodes = flow.GetNodes(); // 找到流程的起始节点,开始运行 - NodeModelBase startNode = flow.GetStartNode(); + IFlowNode startNode = flow.GetStartNode(); // 是否后台运行当前画布流程 if (flow.IsTaskAsync) { @@ -110,7 +110,7 @@ namespace Serein.NodeFlow /// 初始化节点所需的所有类型 /// /// - private bool RegisterAllType(List nodes) + private bool RegisterAllType(List nodes) { var env = WorkOptions.Environment; @@ -248,7 +248,7 @@ namespace Serein.NodeFlow /// /// /// - private async Task CallStartNode(NodeModelBase startNode) + private async Task CallStartNode(IFlowNode startNode) { var pool = WorkOptions.FlowContextPool; var token = WorkOptions.CancellationTokenSource.Token; @@ -268,7 +268,7 @@ namespace Serein.NodeFlow /// /// /// - public async Task StartFlowInSelectNodeAsync(IFlowEnvironment env, NodeModelBase startNode) + public async Task StartFlowInSelectNodeAsync(IFlowEnvironment env, IFlowNode startNode) { var pool = WorkOptions.FlowContextPool; var context = pool.Allocate(); diff --git a/NodeFlow/FlowWorkOptions.cs b/NodeFlow/FlowWorkOptions.cs index 755be81..caf4463 100644 --- a/NodeFlow/FlowWorkOptions.cs +++ b/NodeFlow/FlowWorkOptions.cs @@ -20,12 +20,12 @@ namespace Serein.NodeFlow /// /// 流程起始节点 /// - public Func GetStartNode { get; set; } + public Func GetStartNode { get; set; } /// /// 获取当前画布流程的所有节点 /// - public Func> GetNodes { get; set; } + public Func> GetNodes { get; set; } } /// diff --git a/NodeFlow/Model/NodeModelBaseData.cs b/NodeFlow/Model/NodeModelBaseData.cs new file mode 100644 index 0000000..4fbbdfe --- /dev/null +++ b/NodeFlow/Model/NodeModelBaseData.cs @@ -0,0 +1,157 @@ +using Serein.Library; +using Serein.Library.Api; +using Serein.Library.NodeGenerator; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Net.Mime; +using System.Threading; + +namespace Serein.NodeFlow.Model +{ + + + + /// + /// 节点基类(数据) + /// + [NodeProperty(ValuePath = NodeValuePath.Node)] + public abstract partial class NodeModelBase : IFlowNode + { + /// + /// 节点运行环境 + /// + [PropertyInfo(IsProtection = true)] + private IFlowEnvironment _env; + + /// + /// 标识节点对象全局唯一 + /// + [PropertyInfo(IsProtection = true)] + private string _guid; + + /// + /// 描述节点对应的控件类型 + /// + [PropertyInfo(IsProtection = true)] + private NodeControlType _controlType; + + /// + /// 所属画布 + /// + [PropertyInfo(IsProtection = true)] + private FlowCanvasDetails _canvasDetails ; + + /// + /// 在画布中的位置 + /// + [PropertyInfo(IsProtection = true)] + private PositionOfUI _position ; + + /// + /// 显示名称 + /// + [PropertyInfo] + private string _displayName; + + /// + /// 是否公开 + /// + [PropertyInfo(IsNotification = true)] + private bool _isPublic; + + /* /// + /// 是否保护参数 + /// + [PropertyInfo(IsNotification = true)] + private bool _isProtectionParameter;*/ + + /// + /// 附加的调试功能 + /// + [PropertyInfo(IsProtection = true)] + private NodeDebugSetting _debugSetting ; + + /// + /// 方法描述。包含参数信息。不包含Method与委托,如若需要调用对应的方法,需要通过MethodName从环境中获取委托进行调用。 + /// + [PropertyInfo] + private MethodDetails _methodDetails ; + } + + + public abstract partial class NodeModelBase : IDynamicFlowNode + { + /// + /// 是否为基础节点 + /// + public virtual bool IsBase { get; } = false; + + /// + /// 可以放置多少个节点 + /// + public virtual int MaxChildrenCount { get; } = 0; + + public NodeModelBase(IFlowEnvironment environment) + { + PreviousNodes = new Dictionary>(); + SuccessorNodes = new Dictionary>(); + foreach (ConnectionInvokeType ctType in NodeStaticConfig.ConnectionTypes) + { + PreviousNodes[ctType] = new List(); + SuccessorNodes[ctType] = new List(); + } + ChildrenNode = new List(); + DebugSetting = new NodeDebugSetting(this); + this.Env = environment; + } + + + /// + /// 不同分支的父节点(流程调用) + /// + public Dictionary> PreviousNodes { get; } + + /// + /// 不同分支的子节点(流程调用) + /// + public Dictionary> SuccessorNodes { get; set; } + + /// + /// 该节点的容器节点 + /// + public IFlowNode ContainerNode { get; set; } = null; + + /// + /// 该节点的子项节点(如果该节点是容器节点,那就会有这个参数) + /// + public List ChildrenNode { get; } + + /// + /// 节点公开状态发生改变 + /// + partial void OnIsPublicChanged(bool oldValue, bool newValue) + { + if (newValue) + { + // 公开节点 + if (!CanvasDetails.PublicNodes.Contains(this)) + { + CanvasDetails.PublicNodes.Add(this); + } + } + else + { + // 取消公开 + if (CanvasDetails.PublicNodes.Contains(this)) + { + CanvasDetails.PublicNodes.Remove(this); + } + } + } + + + } + } + + diff --git a/NodeFlow/Model/NodeModelBaseFunc.cs b/NodeFlow/Model/NodeModelBaseFunc.cs new file mode 100644 index 0000000..a56f1db --- /dev/null +++ b/NodeFlow/Model/NodeModelBaseFunc.cs @@ -0,0 +1,151 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Serein.Library; +using Serein.Library.Api; +using Serein.Library.Utils; +using Serein.Library.Utils.SereinExpression; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel.Design; +using System.Linq; +using System.Linq.Expressions; +using System.Net.Http.Headers; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace Serein.NodeFlow.Model +{ + + + + + + + /// + /// 节点基类 + /// + public abstract partial class NodeModelBase : IDynamicFlowNode + { + /// + /// 实体节点创建完成后调用的方法,调用时间早于 LoadInfo() 方法 + /// + public virtual void OnCreating() + { + + } + + /// + /// 保存自定义信息 + /// + /// + public virtual NodeInfo SaveCustomData(NodeInfo nodeInfo) + { + return nodeInfo; + } + + /// + /// 加载自定义数据 + /// + /// + public virtual void LoadCustomData(NodeInfo nodeInfo) + { + return; + } + + /// + /// 移除该节点 + /// + public virtual void Remove() + { + if (this.DebugSetting.CancelInterrupt != null) + { + this.DebugSetting.CancelInterrupt?.Invoke(); + } + + if (this.IsPublic) + { + this.CanvasDetails.PublicNodes.Remove(this); + } + + this.DebugSetting.NodeModel = null; + this.DebugSetting = null; + if(this.MethodDetails is not null) + { + if (this.MethodDetails.ParameterDetailss != null) + { + foreach (var pd in this.MethodDetails.ParameterDetailss) + { + pd.DataValue = null; + pd.Items = null; + pd.NodeModel = null; + pd.ExplicitType = null; + pd.DataType = null; + pd.Name = null; + pd.ArgDataSourceNodeGuid = null; + pd.InputType = ParameterValueInputType.Input; + } + } + this.MethodDetails.ParameterDetailss = null; + this.MethodDetails.NodeModel = null; + this.MethodDetails.ReturnType = null; + this.MethodDetails.ActingInstanceType = null; + this.MethodDetails = null; + } + + this.Position = null; + this.DisplayName = null; + + this.Env = null; + } + + /// + /// 执行节点对应的方法 + /// + /// 流程上下文 + /// + /// 自定义参数 + /// 节点传回数据对象 + public virtual async Task ExecutingAsync(IDynamicContext context, CancellationToken token) + { + // 执行触发检查是否需要中断 + if (DebugSetting.IsInterrupt) + { + context.Env.TriggerInterrupt(Guid, "", InterruptTriggerEventArgs.InterruptTriggerType.Monitor); // 通知运行环境该节点中断了 + await DebugSetting.GetInterruptTask.Invoke(); + SereinEnv.WriteLine(InfoType.INFO, $"[{this.MethodDetails?.MethodName}]中断已取消,开始执行后继分支"); + if (token.IsCancellationRequested) { return null; } + } + + MethodDetails md = MethodDetails; + if (md is null) + { + throw new Exception($"节点{this.Guid}不存在方法信息,请检查是否需要重写节点的ExecutingAsync"); + } + if (!context.Env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd)) // 流程运行到某个节点 + { + + throw new Exception($"节点{this.Guid}不存在对应委托"); + } + + var instance = Env.IOC.Get(md.ActingInstanceType); + if (instance is null) + { + Env.IOC.Register(md.ActingInstanceType).Build(); + instance = Env.IOC.Get(md.ActingInstanceType); + } + object[] args = await this.GetParametersAsync(context, token); + var result = await dd.InvokeAsync(instance, args); + var flowReslt = new FlowResult(this, context, result); + return flowReslt; + + } + + } + + +} diff --git a/NodeFlow/Model/SingleFlowCallNode.cs b/NodeFlow/Model/SingleFlowCallNode.cs index 0302817..cf0a2b5 100644 --- a/NodeFlow/Model/SingleFlowCallNode.cs +++ b/NodeFlow/Model/SingleFlowCallNode.cs @@ -40,7 +40,7 @@ namespace Serein.NodeFlow.Model /// /// 接口节点 /// - private NodeModelBase targetNode; + private IFlowNode targetNode; /// /// 缓存的方法信息 /// diff --git a/NodeFlow/Model/SingleGlobalDataNode.cs b/NodeFlow/Model/SingleGlobalDataNode.cs index e59e106..b74fddb 100644 --- a/NodeFlow/Model/SingleGlobalDataNode.cs +++ b/NodeFlow/Model/SingleGlobalDataNode.cs @@ -49,14 +49,14 @@ namespace Serein.NodeFlow.Model /// /// 数据来源的节点 /// - private NodeModelBase? DataNode; + private IFlowNode? DataNode; /// /// 有节点被放置 /// /// /// - public bool PlaceNode(NodeModelBase nodeModel) + public bool PlaceNode(IFlowNode nodeModel) { if(DataNode is null) { @@ -76,7 +76,7 @@ namespace Serein.NodeFlow.Model } - public bool TakeOutNode(NodeModelBase nodeModel) + public bool TakeOutNode(IFlowNode nodeModel) { if (ChildrenNode.Contains(nodeModel)) { diff --git a/NodeFlow/ScriptFlowApi.cs b/NodeFlow/ScriptFlowApi.cs index 325a976..97150af 100644 --- a/NodeFlow/ScriptFlowApi.cs +++ b/NodeFlow/ScriptFlowApi.cs @@ -22,7 +22,7 @@ namespace Serein.NodeFlow /// /// 对应的节点 /// - public NodeModelBase NodeModel { get; private set; } + public IFlowNode NodeModel { get; private set; } @@ -31,7 +31,7 @@ namespace Serein.NodeFlow /// /// 运行环境 /// 节点 - public ScriptFlowApi(IFlowEnvironment environment, NodeModelBase nodeModel) + public ScriptFlowApi(IFlowEnvironment environment, IFlowNode nodeModel) { Env = environment; NodeModel = nodeModel; diff --git a/Workbench/Node/Junction/JunctionControlBase.cs b/Workbench/Node/Junction/JunctionControlBase.cs index 6f3e6a9..dcb9f1d 100644 --- a/Workbench/Node/Junction/JunctionControlBase.cs +++ b/Workbench/Node/Junction/JunctionControlBase.cs @@ -16,6 +16,7 @@ using Serein.Workbench.Services; using Serein.Workbench.Tool; using System.ComponentModel; using System.Diagnostics; +using Serein.Library.Api; namespace Serein.Workbench.Node.View { @@ -60,15 +61,15 @@ namespace Serein.Workbench.Node.View #region 控件属性,所在的节点 public static readonly DependencyProperty NodeProperty = - DependencyProperty.Register(nameof(MyNode), typeof(NodeModelBase), typeof(ParamsArgControl), new PropertyMetadata(default(NodeModelBase))); + DependencyProperty.Register(nameof(MyNode), typeof(IFlowNode), typeof(ParamsArgControl), new PropertyMetadata(default(IFlowNode))); //public NodeModelBase NodeModel; /// /// 所在的节点 /// - public NodeModelBase MyNode + public IFlowNode MyNode { - get { return (NodeModelBase)GetValue(NodeProperty); } + get { return (IFlowNode)GetValue(NodeProperty); } set { SetValue(NodeProperty, value); } } #endregion @@ -194,15 +195,15 @@ namespace Serein.Workbench.Node.View #region 控件属性,所在的节点 public static readonly DependencyProperty NodeProperty = - DependencyProperty.Register(nameof(MyNode), typeof(NodeModelBase), typeof(JunctionControlBase), new PropertyMetadata(default(NodeModelBase))); + DependencyProperty.Register(nameof(MyNode), typeof(IFlowNode), typeof(JunctionControlBase), new PropertyMetadata(default(IFlowNode))); //public NodeModelBase NodeModel; /// /// 所在的节点 /// - public NodeModelBase MyNode + public IFlowNode MyNode { - get { return (NodeModelBase)GetValue(NodeProperty); } + get { return (IFlowNode)GetValue(NodeProperty); } set { SetValue(NodeProperty, value); } } #endregion diff --git a/Workbench/Node/NodeControlViewModelBase.cs b/Workbench/Node/NodeControlViewModelBase.cs index c3770a3..a876b06 100644 --- a/Workbench/Node/NodeControlViewModelBase.cs +++ b/Workbench/Node/NodeControlViewModelBase.cs @@ -5,6 +5,7 @@ using System.Windows.Controls; using System.Windows.Data; using System; using CommunityToolkit.Mvvm.ComponentModel; +using Serein.Library.Api; namespace Serein.Workbench.Node.ViewModel { @@ -14,9 +15,9 @@ namespace Serein.Workbench.Node.ViewModel ///// ///// 对应的节点实体类 ///// - public NodeModelBase NodeModel { get; } + public IFlowNode NodeModel { get; } - public NodeControlViewModelBase(NodeModelBase nodeModel) + public NodeControlViewModelBase(IFlowNode nodeModel) { NodeModel = nodeModel; diff --git a/Workbench/Node/View/ConnectionControl.cs b/Workbench/Node/View/ConnectionControl.cs index 22ca675..6d27972 100644 --- a/Workbench/Node/View/ConnectionControl.cs +++ b/Workbench/Node/View/ConnectionControl.cs @@ -23,11 +23,11 @@ namespace Serein.Workbench.Node.View /// /// 起始节点 /// - public NodeModelBase StartNode { get; set; } + public IFlowNode StartNode { get; set; } /// /// 目标节点 /// - public NodeModelBase EndNode { get; set; } + public IFlowNode EndNode { get; set; } /// /// 来源于起始节点的(控制点)类型 @@ -63,7 +63,7 @@ namespace Serein.Workbench.Node.View /// /// 对应的视图对象 /// - public NodeModelBase NodeModel { get; set; } + public IFlowNode NodeModel { get; set; } /// /// /// diff --git a/Workbench/Node/ViewModel/FlowCallNodeControlViewModel.cs b/Workbench/Node/ViewModel/FlowCallNodeControlViewModel.cs index cbb74da..0370151 100644 --- a/Workbench/Node/ViewModel/FlowCallNodeControlViewModel.cs +++ b/Workbench/Node/ViewModel/FlowCallNodeControlViewModel.cs @@ -1,5 +1,6 @@ using CommunityToolkit.Mvvm.ComponentModel; using Serein.Library; +using Serein.Library.Api; using Serein.NodeFlow.Model; using Serein.Workbench.Api; using Serein.Workbench.Services; @@ -37,7 +38,7 @@ namespace Serein.Workbench.Node.ViewModel /// 当前所选节点 /// [ObservableProperty] - private NodeModelBase _selectNode; + private IFlowNode _selectNode; [ObservableProperty] @@ -88,7 +89,7 @@ namespace Serein.Workbench.Node.ViewModel FlowCallNode.ResetTargetNode(); } - partial void OnSelectNodeChanged(NodeModelBase value) + partial void OnSelectNodeChanged(IFlowNode value) { if(value is null) { diff --git a/Workbench/Node/ViewModel/UINodeControlViewModel.cs b/Workbench/Node/ViewModel/UINodeControlViewModel.cs index 81f7890..01fabea 100644 --- a/Workbench/Node/ViewModel/UINodeControlViewModel.cs +++ b/Workbench/Node/ViewModel/UINodeControlViewModel.cs @@ -23,7 +23,7 @@ namespace Serein.Workbench.Node.ViewModel private UserControl _nodeUIContent; - public UINodeControlViewModel(NodeModelBase nodeModel) : base(nodeModel) + public UINodeControlViewModel(IFlowNode nodeModel) : base(nodeModel) { } diff --git a/Workbench/Services/FlowNodeService.cs b/Workbench/Services/FlowNodeService.cs index cb0e71a..e5b2ea2 100644 --- a/Workbench/Services/FlowNodeService.cs +++ b/Workbench/Services/FlowNodeService.cs @@ -421,7 +421,7 @@ namespace Serein.Workbench.Services /// 节点所在画布 /// /// 无法创建节点控件 - private static NodeControlBase CreateNodeControl(Type controlType, Type viewModelType, NodeModelBase model, IFlowCanvas nodeCanvas) + private static NodeControlBase CreateNodeControl(Type controlType, Type viewModelType, IFlowNode model, IFlowCanvas nodeCanvas) { if ((controlType is null) || viewModelType is null @@ -489,7 +489,7 @@ namespace Serein.Workbench.Services /// /// 从节点信息转换为Json文本数据 /// - public string CpoyNodeInfo(List dictSelection) + public string CpoyNodeInfo(List dictSelection) { // 遍历当前已选节点 diff --git a/Workbench/Themes/NodeTreeItemViewControl.xaml.cs b/Workbench/Themes/NodeTreeItemViewControl.xaml.cs index 09f4d06..54c9637 100644 --- a/Workbench/Themes/NodeTreeItemViewControl.xaml.cs +++ b/Workbench/Themes/NodeTreeItemViewControl.xaml.cs @@ -26,18 +26,18 @@ namespace Serein.Workbench.Themes /// /// 保存的节点数据 /// - private NodeModelBase nodeModel; + private IFlowNode nodeModel; private IFlowEnvironment flowEnvironment { get; set; } private class NodeTreeModel { - public NodeModelBase RootNode { get; set; } - public Dictionary> ChildNodes { get; set; } + public IFlowNode RootNode { get; set; } + public Dictionary> ChildNodes { get; set; } } - public void InitAndLoadTree(IFlowEnvironment flowEnvironment, NodeModelBase nodeModel) + public void InitAndLoadTree(IFlowEnvironment flowEnvironment, IFlowNode nodeModel) { this.flowEnvironment = flowEnvironment; this.nodeModel = nodeModel; @@ -46,11 +46,11 @@ namespace Serein.Workbench.Themes public TreeViewItem RefreshTree() { - NodeModelBase rootNodeModel = this.nodeModel; + IFlowNode rootNodeModel = this.nodeModel; NodeTreeModel nodeTreeModel = new NodeTreeModel { RootNode = rootNodeModel, - ChildNodes = new Dictionary>() + ChildNodes = new Dictionary>() { {ConnectionInvokeType.Upstream, []}, {ConnectionInvokeType.IsSucceed, [rootNodeModel]}, diff --git a/Workbench/Themes/NodeTreeViewControl.xaml.cs b/Workbench/Themes/NodeTreeViewControl.xaml.cs index 08f8c11..769b120 100644 --- a/Workbench/Themes/NodeTreeViewControl.xaml.cs +++ b/Workbench/Themes/NodeTreeViewControl.xaml.cs @@ -18,14 +18,14 @@ namespace Serein.Workbench.Themes private Dictionary globalFlipflopNodes = []; private Dictionary unemployedNodes = []; - public void LoadNodeTreeOfStartNode(IFlowEnvironment flowEnvironment, NodeModelBase nodeModel) + public void LoadNodeTreeOfStartNode(IFlowEnvironment flowEnvironment, IFlowNode nodeModel) { startNodeGuid = nodeModel.Guid; StartNodeViewer.InitAndLoadTree(flowEnvironment, nodeModel); } #region 触发器 - public void AddGlobalFlipFlop(IFlowEnvironment flowEnvironment, NodeModelBase nodeModel) + public void AddGlobalFlipFlop(IFlowEnvironment flowEnvironment, IFlowNode nodeModel) { if (!globalFlipflopNodes.ContainsKey(nodeModel.Guid)) { @@ -35,14 +35,14 @@ namespace Serein.Workbench.Themes GlobalFlipflopNodeListbox.Items.Add(flipflopTreeViewer); } } - public void RefreshGlobalFlipFlop(NodeModelBase nodeModel) + public void RefreshGlobalFlipFlop(IFlowNode nodeModel) { if (globalFlipflopNodes.TryGetValue(nodeModel.Guid, out var viewer)) { viewer.RefreshTree(); } } - public void RemoveGlobalFlipFlop(NodeModelBase nodeModel) + public void RemoveGlobalFlipFlop(IFlowNode nodeModel) { if (globalFlipflopNodes.TryGetValue(nodeModel.Guid, out var viewer)) { @@ -54,7 +54,7 @@ namespace Serein.Workbench.Themes #region 无业游民(定义:不存在于起始节点与全局触发器的调用链上的节点,只能手动刷新?) - public void AddUnemployed(IFlowEnvironment flowEnvironment, NodeModelBase nodeModel) + public void AddUnemployed(IFlowEnvironment flowEnvironment, IFlowNode nodeModel) { if (!unemployedNodes.ContainsKey(nodeModel.Guid)) { @@ -64,14 +64,14 @@ namespace Serein.Workbench.Themes GlobalFlipflopNodeListbox.Items.Add(flipflopTreeViewer); } } - public void RefreshUnemployed(NodeModelBase nodeModel) + public void RefreshUnemployed(IFlowNode nodeModel) { if (unemployedNodes.TryGetValue(nodeModel.Guid, out var viewer)) { viewer.RefreshTree(); } } - public void RemoteUnemployed(NodeModelBase nodeModel) + public void RemoteUnemployed( IFlowNode nodeModel) { if (unemployedNodes.TryGetValue(nodeModel.Guid, out var viewer)) { diff --git a/Workbench/ViewModels/ViewNodeInfoViewModel.cs b/Workbench/ViewModels/ViewNodeInfoViewModel.cs index 1b63962..1b452cf 100644 --- a/Workbench/ViewModels/ViewNodeInfoViewModel.cs +++ b/Workbench/ViewModels/ViewNodeInfoViewModel.cs @@ -1,5 +1,6 @@ using CommunityToolkit.Mvvm.ComponentModel; using Serein.Library; +using Serein.Library.Api; using Serein.Workbench.Node.View; using Serein.Workbench.Services; using System; @@ -18,7 +19,7 @@ namespace Serein.Workbench.ViewModels /// 当前预览的节点 /// [ObservableProperty] - private NodeModelBase viewNodeModel; + private IFlowNode viewNodeModel; public ViewNodeInfoViewModel(FlowNodeService flowNodeService) { diff --git a/Workbench/Views/ViewCanvasInfoView.xaml.cs b/Workbench/Views/ViewCanvasInfoView.xaml.cs index 303f572..eef6097 100644 --- a/Workbench/Views/ViewCanvasInfoView.xaml.cs +++ b/Workbench/Views/ViewCanvasInfoView.xaml.cs @@ -36,7 +36,7 @@ namespace Serein.Workbench.Views private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { - if (sender is Grid grid && grid.DataContext is NodeModelBase nodeModel) + if (sender is Grid grid && grid.DataContext is IFlowNode nodeModel) { NodeInfoViewModel.ViewNodeModel = nodeModel; App.GetService().NodeLocated(nodeModel.Guid);