1. 重新设计了Generate项目及相关特性的命名,避免与其他类型混淆。

2. 补充了部分注释。
3. 修改了删除容器节点时,容器内子节点未正确删除的问题。
This commit is contained in:
fengjiayi
2025-07-30 21:15:07 +08:00
parent 93148b11a5
commit 152077e9b5
188 changed files with 2713 additions and 1406 deletions

View File

@@ -143,7 +143,7 @@ namespace Serein.NodeFlow.Model.Library
// 从 scanTypes.Type 创建的方法信息
// Md : 方法描述
// Dd 方法对应的Emit委托
List<LibraryMdDd> detailss = new List<LibraryMdDd>();
List<LibraryMthodInfo> detailss = new List<LibraryMthodInfo>();
// 遍历扫描的类型
foreach ((var type, var flowName) in scanTypes)
@@ -159,7 +159,7 @@ namespace Serein.NodeFlow.Model.Library
continue;
}
md.MethodAnotherName = flowName + md.MethodAnotherName; // 方法别名
detailss.Add(new LibraryMdDd(mi, md, dd));
detailss.Add(new LibraryMthodInfo(mi, md, dd));
}
}

View File

@@ -1,20 +0,0 @@
using Serein.Library;
using System.Reflection;
namespace Serein.NodeFlow.Model.Library
{
public class LibraryMdDd
{
public MethodDetails MethodDetails { get; }
public MethodInfo MethodInfo { get; }
public DelegateDetails DelegateDetails { get; }
public LibraryMdDd(MethodInfo methodInfo, MethodDetails methodDetails, DelegateDetails delegateDetails)
{
MethodDetails = methodDetails;
MethodInfo = methodInfo;
DelegateDetails = delegateDetails;
}
}
}

View File

@@ -0,0 +1,39 @@
using Serein.Library;
using System.Reflection;
namespace Serein.NodeFlow.Model.Library
{
/// <summary>
/// 库方法信息类,包含方法的详细信息、反射信息和委托信息。
/// </summary>
public class LibraryMthodInfo
{
/// <summary>
/// 方法的详细信息。
/// </summary>
public MethodDetails MethodDetails { get; }
/// <summary>
/// 方法的反射信息,包含方法名称、参数类型等。
/// </summary>
public MethodInfo MethodInfo { get; }
/// <summary>
/// Emit构造委托
/// </summary>
public DelegateDetails DelegateDetails { get; }
/// <summary>
/// 构造一个新的库方法信息实例。
/// </summary>
/// <param name="methodInfo"></param>
/// <param name="methodDetails"></param>
/// <param name="delegateDetails"></param>
public LibraryMthodInfo(MethodInfo methodInfo, MethodDetails methodDetails, DelegateDetails delegateDetails)
{
MethodDetails = methodDetails;
MethodInfo = methodInfo;
DelegateDetails = delegateDetails;
}
}
}

View File

@@ -140,7 +140,6 @@ namespace Serein.NodeFlow.Model.Nodes
/// 从节点信息加载节点
/// </summary>
/// <param name="nodeModel"></param>
/// <param name="canvas"></param>
/// <param name="nodeInfo"></param>
/// <returns></returns>
public static void LoadInfo(this IFlowNode nodeModel, NodeInfo nodeInfo)
@@ -243,97 +242,6 @@ namespace Serein.NodeFlow.Model.Nodes
}
}
/// <summary>
/// 检查监视表达式是否生效
/// </summary>
/// <param name="nodeModel">节点Moel</param>
/// <param name="context">上下文</param>
/// <param name="newData">新的数据</param>
/// <returns></returns>
/*public static async Task CheckExpInterrupt(this NodeModelBase nodeModel, IDynamicContext context, object newData = null)
{
string guid = nodeModel.Guid;
context.AddOrUpdate(guid, newData); // 上下文中更新数据
if (newData is null)
{
}
else
{
await nodeModel.MonitorObjExpInterrupt(context, newData, 0); // 首先监视对象
await nodeModel.MonitorObjExpInterrupt(context, newData, 1); // 然后监视节点
//nodeModel.FlowData = newData; // 替换数据
}
}*/
/// <summary>
/// 监视对象表达式中断
/// </summary>
/// <param name="nodeModel"></param>
/// <param name="context"></param>
/// <param name="data"></param>
/// <param name="monitorType"></param>
/// <returns></returns>
/*private static async Task MonitorObjExpInterrupt(this NodeModelBase nodeModel, IDynamicContext context, object data, int monitorType)
{
MonitorObjectEventArgs.ObjSourceType sourceType;
string key;
if (monitorType == 0)
{
key = data?.GetType()?.FullName;
sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
}
else
{
key = nodeModel.Guid;
sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
}
if (string.IsNullOrEmpty(key))
{
return;
}
//(var isMonitor, var exps) = await context.Env.CheckObjMonitorStateAsync(key);
//if (isMonitor) // 如果新的数据处于查看状态通知UI进行更新交给运行环境判断
//{
// context.Env.MonitorObjectNotification(nodeModel.Guid, data, sourceType); // 对象处于监视状态通知UI更新数据显示
// if (exps.Length > 0)
// {
// // 表达式环境下判断是否需要执行中断
// bool isExpInterrupt = false;
// string exp = "";
// // 判断执行监视表达式,直到为 true 时退出
// for (int i = 0; i < exps.Length && !isExpInterrupt; i++)
// {
// exp = exps[i];
// if (string.IsNullOrEmpty(exp)) continue;
// // isExpInterrupt = SereinConditionParser.To(data, exp);
// }
// if (isExpInterrupt) // 触发中断
// {
// nodeModel.DebugSetting.IsInterrupt = true;
// if (await context.Env.SetNodeInterruptAsync(nodeModel.Guid,true))
// {
// context.Env.TriggerInterrupt(nodeModel.Guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Exp);
// var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
// await Console.Out.WriteLineAsync($"[{data}]中断已{cancelType},开始执行后继分支");
// nodeModel.DebugSetting.IsInterrupt = false;
// }
// }
// }
//}
}*/
/// <summary>
/// 不再中断
/// </summary>
public static void CancelInterrupt(IFlowNode nodeModel)
{
nodeModel.DebugSetting.IsInterrupt = false;
nodeModel.DebugSetting.CancelInterrupt?.Invoke();
}
#if DEBUG
/// <summary>
/// 程序集更新,更新节点方法描述、以及所有入参描述的类型

View File

@@ -13,49 +13,49 @@ namespace Serein.NodeFlow.Model.Nodes
/// <summary>
/// 节点基类(数据)
/// </summary>
[NodeProperty(ValuePath = NodeValuePath.Node)]
[FlowDataProperty(ValuePath = NodeValuePath.Node)]
public abstract partial class NodeModelBase : IFlowNode
{
/// <summary>
/// 节点运行环境
/// </summary>
[PropertyInfo(IsProtection = true)]
[DataInfo(IsProtection = true)]
private IFlowEnvironment _env;
/// <summary>
/// 标识节点对象全局唯一
/// </summary>
[PropertyInfo(IsProtection = true)]
[DataInfo(IsProtection = true)]
private string _guid;
/// <summary>
/// 描述节点对应的控件类型
/// </summary>
[PropertyInfo(IsProtection = true)]
[DataInfo(IsProtection = true)]
private NodeControlType _controlType;
/// <summary>
/// 所属画布
/// </summary>
[PropertyInfo(IsProtection = true)]
[DataInfo(IsProtection = true)]
private FlowCanvasDetails _canvasDetails ;
/// <summary>
/// 在画布中的位置
/// </summary>
[PropertyInfo(IsProtection = true)]
[DataInfo(IsProtection = true)]
private PositionOfUI _position ;
/// <summary>
/// 显示名称
/// </summary>
[PropertyInfo]
[DataInfo]
private string _displayName;
/// <summary>
/// 是否公开
/// </summary>
[PropertyInfo(IsNotification = true)]
[DataInfo(IsNotification = true)]
private bool _isPublic;
/* /// <summary>
@@ -67,13 +67,13 @@ namespace Serein.NodeFlow.Model.Nodes
/// <summary>
/// 附加的调试功能
/// </summary>
[PropertyInfo(IsProtection = true)]
[DataInfo(IsProtection = true)]
private NodeDebugSetting _debugSetting ;
/// <summary>
/// 方法描述。包含参数信息。不包含Method与委托如若需要调用对应的方法需要通过MethodName从环境中获取委托进行调用。
/// </summary>
[PropertyInfo]
[DataInfo]
private MethodDetails _methodDetails ;
}
@@ -90,6 +90,10 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
public virtual int MaxChildrenCount { get; } = 0;
/// <summary>
/// 创建一个节点模型的基类实例
/// </summary>
/// <param name="environment"></param>
public NodeModelBase(IFlowEnvironment environment)
{
PreviousNodes = new Dictionary<ConnectionInvokeType, List<IFlowNode>>();

View File

@@ -47,7 +47,6 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
/// <param name="context">流程上下文</param>
/// <param name="token"></param>
/// <param name="args">自定义参数</param>
/// <returns>节点传回数据对象</returns>
public virtual async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
{

View File

@@ -9,6 +9,10 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
public class SingleActionNode : NodeModelBase
{
/// <summary>
/// 构造一个新的单动作节点实例。
/// </summary>
/// <param name="environment"></param>
public SingleActionNode(IFlowEnvironment environment):base(environment)
{

View File

@@ -9,25 +9,25 @@ namespace Serein.NodeFlow.Model.Nodes
/// <summary>
/// 条件节点(用于条件控件)
/// </summary>
[NodeProperty(ValuePath = NodeValuePath.Node)]
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
public partial class SingleConditionNode : NodeModelBase
{
/// <summary>
/// 是否为自定义参数
/// </summary>
[PropertyInfo(IsNotification = true)]
[DataInfo(IsNotification = true)]
private bool _isExplicitData;
/// <summary>
/// 自定义参数值
/// </summary>
[PropertyInfo(IsNotification = true)]
[DataInfo(IsNotification = true)]
private string? _explicitData;
/// <summary>
/// 条件表达式
/// </summary>
[PropertyInfo(IsNotification = true)]
[DataInfo(IsNotification = true)]
private string _expression;
}
@@ -44,7 +44,10 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
private const int INDEX_EXPRESSION = 0;
/// <summary>
/// 条件节点构造函数
/// </summary>
/// <param name="environment"></param>
public SingleConditionNode(IFlowEnvironment environment):base(environment)
{
this.IsExplicitData = false;
@@ -52,6 +55,9 @@ namespace Serein.NodeFlow.Model.Nodes
this.Expression = "PASS";
}
/// <summary>
/// 创建节点时调用的方法
/// </summary>
public override void OnCreating()
{
// 这里的这个参数是为了方便使用入参控制点,参数无意义
@@ -106,6 +112,7 @@ namespace Serein.NodeFlow.Model.Nodes
/// 重写节点的方法执行
/// </summary>
/// <param name="context"></param>
/// <param name="token"></param>
/// <returns></returns>
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
{

View File

@@ -8,19 +8,21 @@ namespace Serein.NodeFlow.Model.Nodes
/// <summary>
/// Expression Operation - 表达式操作
/// </summary>
[NodeProperty(ValuePath = NodeValuePath.Node)]
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
public partial class SingleExpOpNode : NodeModelBase
{
/// <summary>
/// 表达式
/// </summary>
[PropertyInfo(IsNotification = true)]
[DataInfo(IsNotification = true)]
private string _expression;
}
/// <summary>
/// 表达式节点模型基类
/// </summary>
public partial class SingleExpOpNode : NodeModelBase
{
/// <summary>
@@ -33,6 +35,10 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
private const int INDEX_EXPRESSION = 0;
/// <summary>
/// 表达式节点构造函数
/// </summary>
/// <param name="environment"></param>
public SingleExpOpNode(IFlowEnvironment environment) : base(environment)
{
@@ -87,7 +93,12 @@ namespace Serein.NodeFlow.Model.Nodes
this.Expression = nodeInfo.CustomData?.Expression ?? "";
}
/// <summary>
/// 执行节点操作
/// </summary>
/// <param name="context"></param>
/// <param name="token"></param>
/// <returns></returns>
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
{
if(token.IsCancellationRequested) return FlowResult.Fail(this.Guid, context, "流程已通过token取消");

View File

@@ -10,7 +10,10 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
public class SingleFlipflopNode : NodeModelBase
{
/// <summary>
/// 构造一个新的单触发器节点实例。
/// </summary>
/// <param name="environment"></param>
public SingleFlipflopNode(IFlowEnvironment environment) : base(environment)
{
@@ -21,6 +24,7 @@ namespace Serein.NodeFlow.Model.Nodes
/// 执行触发器进行等待触发
/// </summary>
/// <param name="context"></param>
/// <param name="token"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)

View File

@@ -7,26 +7,26 @@ using System.Reflection;
namespace Serein.NodeFlow.Model.Nodes
{
[NodeProperty(ValuePath = NodeValuePath.Node)]
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
public partial class SingleFlowCallNode
{
/// <summary>
/// 目标公开节点
/// </summary>
[PropertyInfo(IsNotification = true)]
private string targetNodeGuid;
[DataInfo(IsNotification = true)]
private string targetNodeGuid = string.Empty;
/// <summary>
/// 使用目标节点的参数如果为true则使用目标节点的入参如果为false则使用节点自定义入参
/// </summary>
[PropertyInfo(IsNotification = true)]
private bool _isShareParam ;
[DataInfo(IsNotification = true)]
private bool _isShareParam ;
/// <summary>
/// 接口全局名称
/// </summary>
[PropertyInfo(IsNotification = true)]
private string _apiGlobalName;
[DataInfo(IsNotification = true)]
private string _apiGlobalName = string.Empty;
}
@@ -45,6 +45,10 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
public MethodDetails CacheMethodDetails { get; private set; }
/// <summary>
/// 流程接口节点
/// </summary>
/// <param name="environment"></param>
public SingleFlowCallNode(IFlowEnvironment environment) : base(environment)
{
@@ -207,7 +211,7 @@ namespace Serein.NodeFlow.Model.Nodes
}
private static Dictionary<string, int> ApiInvokeNameCache = new Dictionary<string, int>();
public static int getApiInvokeNameCount = 0;
private static int getApiInvokeNameCount = 0;
private static string GetApiInvokeName(SingleFlowCallNode node, string apiName)
{
if (ApiInvokeNameCache.ContainsKey(apiName))
@@ -223,6 +227,12 @@ namespace Serein.NodeFlow.Model.Nodes
return $"{apiName}";
}
}
/// <summary>
/// 获取流程接口节点的名称
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public static string GetApiInvokeName(SingleFlowCallNode node)
{
if(node.TargetNode is null)

View File

@@ -9,13 +9,13 @@ namespace Serein.NodeFlow.Model.Nodes
/// <summary>
/// Expression Operation - 表达式操作
/// </summary>
[NodeProperty(ValuePath = NodeValuePath.Node)]
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
public partial class SingleGlobalDataNode : NodeModelBase
{
/// <summary>
/// 全局数据的Key名称
/// </summary>
[PropertyInfo(IsNotification = true)]
[DataInfo(IsNotification = true)]
private string _keyName;
}
@@ -36,6 +36,10 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
public override int MaxChildrenCount => 1;
/// <summary>
/// 全局数据节点,允许放置一个数据源节点,通常是[Action]或[Script]节点,用于获取全局数据。
/// </summary>
/// <param name="environment"></param>
public SingleGlobalDataNode(IFlowEnvironment environment) : base(environment)
{
}
@@ -85,7 +89,11 @@ namespace Serein.NodeFlow.Model.Nodes
}
/// <summary>
/// 从容器中取出节点
/// </summary>
/// <param name="nodeModel"></param>
/// <returns></returns>
public bool TakeOutNode(IFlowNode nodeModel)
{
if (ChildrenNode.Contains(nodeModel))
@@ -102,7 +110,10 @@ namespace Serein.NodeFlow.Model.Nodes
}
public async void TakeOutAll()
/// <summary>
/// 从容器中取出所有节点
/// </summary>
public void TakeOutAll()
{
foreach (var nodeModel in ChildrenNode)
{
@@ -111,12 +122,13 @@ namespace Serein.NodeFlow.Model.Nodes
DataNode = null;
}
/// <summary>
/// 设置全局数据
/// </summary>
/// <param name="context"></param>
/// <param name="token"></param>
/// <returns></returns>
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
{

View File

@@ -10,27 +10,30 @@ using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Nodes
{
/// <summary>
/// 单脚本节点(用于脚本控件)
/// </summary>
[NodeProperty(ValuePath = NodeValuePath.Node)]
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
public partial class SingleNetScriptNode : NodeModelBase
{
/// <summary>
/// 脚本代码
/// </summary>
[PropertyInfo(IsNotification = true)]
private string _script;
[DataInfo(IsNotification = true)]
private string _script = string.Empty;
/// <summary>
/// 功能提示
/// </summary>
[PropertyInfo(IsNotification = true)]
[DataInfo(IsNotification = true)]
private string _tips = "写一下提示吧";
/// <summary>
/// 依赖路径
/// </summary>
[PropertyInfo(IsNotification = true)]
private List<string> _libraryFilePaths;
[DataInfo(IsNotification = true)]
private List<string> _libraryFilePaths = [];
}
@@ -41,46 +44,16 @@ namespace Serein.NodeFlow.Model.Nodes
/// </summary>
public override bool IsBase => true;
/// <summary>
/// 脚本代码
/// </summary>
/// <param name="environment"></param>
public SingleNetScriptNode(IFlowEnvironment environment) : base(environment)
{
this.Env = environment;
}
public override void OnCreating()
{
//MethodInfo? method = this.GetType().GetMethod(nameof(GetFlowApi));
//if (method != null)
//{
// ScriptInterpreter.AddFunction(nameof(GetFlowApi), method, () => this); // 挂载获取流程接口
//}
//var md = MethodDetails;
//var pd = md.ParameterDetailss ??= new ParameterDetails[1];
//md.ParamsArgIndex = 0;
//pd[0] = new ParameterDetails
//{
// Index = 0,
// Name = "object",
// IsExplicitData = true,
// DataValue = string.Empty,
// DataType = typeof(object),
// ExplicitType = typeof(object),
// ArgDataSourceNodeGuid = string.Empty,
// ArgDataSourceType = ConnectionArgSourceType.GetPreviousNodeData,
// NodeModel = this,
// InputType = ParameterValueInputType.Input,
// Items = null,
// IsParams = true,
// Description = "脚本节点入参"
//};
}
/// <summary>
/// 导出脚本代码
/// </summary>

View File

@@ -18,11 +18,11 @@ using System.Xml.Linq;
namespace Serein.NodeFlow.Model.Nodes
{
[NodeProperty(ValuePath = NodeValuePath.Node)]
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
public partial class SingleScriptNode : NodeModelBase
{
[PropertyInfo(IsNotification = true)]
private string _script;
[DataInfo(IsNotification = true)]
private string _script = string.Empty;
}
/// <summary>
@@ -293,6 +293,7 @@ namespace Serein.NodeFlow.Model.Nodes
/// 执行脚本
/// </summary>
/// <param name="context"></param>
/// <param name="token"></param>
/// <returns></returns>
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
{

View File

@@ -8,13 +8,30 @@ using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Nodes
{
/// <summary>
/// 单个UI节点适用于需要在流程中嵌入用户自定义控件的场景。
/// </summary>
public class SingleUINode : NodeModelBase
{
public IEmbeddedContent Adapter { get; private set; }
/// <summary>
/// 适配的UI控件必须实现IEmbeddedContent接口。
/// </summary>
public IEmbeddedContent? Adapter { get; private set; }
/// <summary>
/// 单个UI节点构造函数初始化流程环境。
/// </summary>
/// <param name="environment"></param>
public SingleUINode(IFlowEnvironment environment) : base(environment)
{
}
/// <summary>
/// 执行节点逻辑适用于嵌入式UI控件的流程节点。
/// </summary>
/// <param name="context"></param>
/// <param name="token"></param>
/// <returns></returns>
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
{
if (token.IsCancellationRequested) return FlowResult.Fail(this.Guid, context, "流程已通过token取消");

View File

@@ -11,7 +11,7 @@ using System.Text;
using System.Threading.Tasks;
using static Serein.Library.Api.NodeConnectChangeEventArgs;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
/// <summary>
/// 节点连接状态发生改变
@@ -45,6 +45,7 @@ namespace Serein.NodeFlow.Model.Operation
/// </summary>
public JunctionType ToNodeJunctionType { get; set; }
/// <summary>
/// 连接类型
/// </summary>
public ConnectionInvokeType ConnectionInvokeType { get; set; }
@@ -69,9 +70,9 @@ namespace Serein.NodeFlow.Model.Operation
public override bool IsCanUndo => false;
#region
private FlowCanvasDetails FlowCanvas;
private IFlowNode FromNode;
private IFlowNode ToNode;
private FlowCanvasDetails? FlowCanvas;
private IFlowNode? FromNode;
private IFlowNode? ToNode;
#endregion
public override bool ValidationParameter()
@@ -155,7 +156,10 @@ namespace Serein.NodeFlow.Model.Operation
/// </summary>
private async Task<bool> CreateInvokeConnection()
{
IFlowNode fromNode = FromNode ;
ArgumentNullException.ThrowIfNull(FlowCanvas);
ArgumentNullException.ThrowIfNull(FromNode);
ArgumentNullException.ThrowIfNull(ToNode);
IFlowNode fromNode = FromNode;
IFlowNode toNode = ToNode;
ConnectionInvokeType invokeType = ConnectionInvokeType;
if (fromNode.ControlType == NodeControlType.FlowCall)
@@ -340,6 +344,10 @@ namespace Serein.NodeFlow.Model.Operation
/// </summary>
private async Task<bool> RemoveInvokeConnection()
{
ArgumentNullException.ThrowIfNull(FlowCanvas);
ArgumentNullException.ThrowIfNull(FromNode);
ArgumentNullException.ThrowIfNull(ToNode);
FromNode.SuccessorNodes[ConnectionInvokeType].Remove(ToNode);
ToNode.PreviousNodes[ConnectionInvokeType].Remove(FromNode);
@@ -383,7 +391,12 @@ namespace Serein.NodeFlow.Model.Operation
/// </summary>
/// <exception cref="Exception"></exception>
private async Task<bool> CreateArgConnection()
{/*
{
ArgumentNullException.ThrowIfNull(FlowCanvas);
ArgumentNullException.ThrowIfNull(FromNode);
ArgumentNullException.ThrowIfNull(ToNode);
/*
IFlowNode fromNodeControl = ToNode;
IFlowNode toNodeControl = ToNode;*/
ConnectionArgSourceType type = ConnectionArgSourceType;
@@ -520,11 +533,12 @@ namespace Serein.NodeFlow.Model.Operation
/// <summary>
/// 移除参数连接关系
/// </summary>
/// <param name="fromNodeControl"></param>
/// <param name="toNodeControl"></param>
/// <param name="index"></param>
private async Task<bool> RemoveArgConnection()
{
ArgumentNullException.ThrowIfNull(FlowCanvas);
ArgumentNullException.ThrowIfNull(FromNode);
ArgumentNullException.ThrowIfNull(ToNode);
if (ToNode.MethodDetails.ParameterDetailss is null) return false;
var type = ToNode.MethodDetails.ParameterDetailss[ArgIndex].ArgDataSourceType;
FromNode.NeedResultNodes[type].Remove(ToNode);

View File

@@ -7,7 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
internal class ChangeParameterOperation : OperationBase
{

View File

@@ -9,7 +9,7 @@ using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
/// <summary>
/// 放置节点操作

View File

@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
/// <summary>

View File

@@ -7,7 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
internal class CreateCanvasOperation : OperationBase
{

View File

@@ -9,7 +9,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
internal class CreateNodeOperation : OperationBase
{

View File

@@ -9,7 +9,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
internal interface IOperation
{
@@ -64,6 +64,7 @@ namespace Serein.NodeFlow.Model.Operation
[AutoInjection]
protected IFlowEnvironmentEvent flowEnvironmentEvent;
public abstract string Theme { get;}
/// <summary>

View File

@@ -7,7 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
internal class RemoveCanvasOperation : OperationBase
{

View File

@@ -2,7 +2,7 @@
using Serein.Library.Api;
using System.Reflection.Metadata;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
internal class RemoveNodeOperation : OperationBase
{
@@ -15,6 +15,7 @@ namespace Serein.NodeFlow.Model.Operation
/// 节点所在画布
/// </summary>
private FlowCanvasDetails flowCanvasDetails;
/// <summary>
/// 被删除的节点
/// </summary>
@@ -46,9 +47,19 @@ namespace Serein.NodeFlow.Model.Operation
{
if (!ValidationParameter()) return false;
// 需要移除对应的方法调用、以及参数获取调用
// 需要移除对应的方法调用、参数获取调用以及子节点信息
// 还需要记录移除的事件参数,用以撤销恢复
if (flowNode.ChildrenNode.Count > 0)
{
// 如果该节点存在子节点,则删除所有子节点
foreach(var child in flowNode.ChildrenNode)
{
flowEnvironment.FlowEdit.RemoveNode(CanvasGuid, child.Guid);
}
}
#region
// 检查该节点的前继节点,然后从这些前继节点中移除与该节点的连接关系

View File

@@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
/// <summary>

View File

@@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model.Operation
namespace Serein.NodeFlow.Model.Operations
{
/// <summary>
/// 设置起始节点