2025-07-27 23:34:01 +08:00
|
|
|
|
using Serein.Library;
|
2025-06-22 21:53:37 +08:00
|
|
|
|
using Serein.Library.Api;
|
2025-07-04 11:35:34 +08:00
|
|
|
|
using Serein.NodeFlow.Model;
|
2025-07-29 14:25:31 +08:00
|
|
|
|
using Serein.NodeFlow.Model.Nodes;
|
2025-07-30 21:15:07 +08:00
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2025-06-22 21:53:37 +08:00
|
|
|
|
|
|
|
|
|
|
namespace Serein.NodeFlow.Services
|
|
|
|
|
|
{
|
2025-07-04 15:46:29 +08:00
|
|
|
|
/// <summary>
|
2026-01-27 17:24:19 +08:00
|
|
|
|
/// 流程画布/节点数据实体服务
|
2025-07-04 15:46:29 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class FlowModelService
|
2025-06-22 21:53:37 +08:00
|
|
|
|
{
|
|
|
|
|
|
private readonly IFlowEnvironment environment;
|
2026-01-27 17:24:19 +08:00
|
|
|
|
private readonly IFlowLibraryService flowLibraryService;
|
2025-06-22 21:53:37 +08:00
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 流程模型服务构造函数
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="environment"></param>
|
|
|
|
|
|
/// <param name="flowLibraryService"></param>
|
2026-01-27 17:24:19 +08:00
|
|
|
|
public FlowModelService(IFlowEnvironment environment, IFlowLibraryService flowLibraryService)
|
2025-06-22 21:53:37 +08:00
|
|
|
|
{
|
|
|
|
|
|
this.environment = environment;
|
2025-07-07 20:40:24 +08:00
|
|
|
|
this.flowLibraryService = flowLibraryService;
|
2025-06-22 21:53:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 环境加载的节点集合
|
|
|
|
|
|
/// Node Guid - Node Model
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private Dictionary<string, IFlowNode> NodeModels { get; } = [];
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 运行环境加载的画布集合
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private Dictionary<string, FlowCanvasDetails> FlowCanvass { get; } = [];
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 存放触发器节点(运行时全部调用)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取节点模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="guid"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public IFlowNode? GetNodeModel(string guid)
|
|
|
|
|
|
{
|
|
|
|
|
|
NodeModels.TryGetValue(guid, out var nodeModel);
|
|
|
|
|
|
return nodeModel;
|
|
|
|
|
|
}
|
2025-07-08 14:22:41 +08:00
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取画布模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="guid"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public FlowCanvasDetails? GetCanvasModel(string guid)
|
|
|
|
|
|
{
|
|
|
|
|
|
FlowCanvass.TryGetValue(guid, out var nodeModel);
|
|
|
|
|
|
return nodeModel;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 尝试获取节点模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="guid"></param>
|
|
|
|
|
|
/// <param name="flowNode"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public bool TryGetNodeModel(string guid, [NotNullWhen(true)] out IFlowNode? flowNode)
|
2025-06-22 21:53:37 +08:00
|
|
|
|
{
|
|
|
|
|
|
return NodeModels.TryGetValue(guid, out flowNode!);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 尝试获取画布模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="guid"></param>
|
|
|
|
|
|
/// <param name="flowCanvas"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public bool TryGetCanvasModel(string guid, [NotNullWhen(true)] out FlowCanvasDetails? flowCanvas)
|
2025-06-22 21:53:37 +08:00
|
|
|
|
{
|
2025-07-30 21:15:07 +08:00
|
|
|
|
if(FlowCanvass.TryGetValue(guid, out var details))
|
|
|
|
|
|
{
|
|
|
|
|
|
flowCanvas = details;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
flowCanvas = details;
|
|
|
|
|
|
return false;
|
2025-06-22 21:53:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 检查是否包含节点模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="guid"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public bool ContainsNodeModel(string guid)
|
|
|
|
|
|
{
|
|
|
|
|
|
return NodeModels.ContainsKey(guid);
|
|
|
|
|
|
}
|
2025-07-08 14:22:41 +08:00
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 检查是否包含画布模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="guid"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public bool ContainsCanvasModel(string guid)
|
|
|
|
|
|
{
|
|
|
|
|
|
return FlowCanvass.ContainsKey(guid);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加节点模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="flowNode"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public bool AddNodeModel(IFlowNode flowNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(flowNode);
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(flowNode.Guid);
|
|
|
|
|
|
return NodeModels.TryAdd(flowNode.Guid, flowNode);
|
|
|
|
|
|
}
|
2025-07-30 21:15:07 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加画布模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="flowCanvasDetails"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public bool AddCanvasModel(FlowCanvasDetails flowCanvasDetails)
|
|
|
|
|
|
{
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(flowCanvasDetails);
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(flowCanvasDetails.Guid);
|
|
|
|
|
|
return FlowCanvass.TryAdd(flowCanvasDetails.Guid, flowCanvasDetails);
|
|
|
|
|
|
}
|
2025-07-30 21:15:07 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 移除节点模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="flowNode"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public bool RemoveNodeModel(IFlowNode flowNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(flowNode.Guid);
|
|
|
|
|
|
return NodeModels.Remove(flowNode.Guid);
|
|
|
|
|
|
}
|
2025-07-30 21:15:07 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 移除画布模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="flowCanvasDetails"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public bool RemoveCanvasModel(FlowCanvasDetails flowCanvasDetails)
|
|
|
|
|
|
{
|
|
|
|
|
|
ArgumentNullException.ThrowIfNull(flowCanvasDetails.Guid);
|
|
|
|
|
|
return FlowCanvass.Remove(flowCanvasDetails.Guid);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取所有节点模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public List<IFlowNode> GetAllNodeModel() => [.. NodeModels.Values];
|
2025-07-30 21:15:07 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取指定画布上的所有节点模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="canvasGuid"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-07-04 15:46:29 +08:00
|
|
|
|
public List<IFlowNode> GetAllNodeModel(string canvasGuid) =>
|
|
|
|
|
|
NodeModels.Values.Where(x => x.CanvasDetails.Guid == canvasGuid).ToList();
|
2025-07-30 21:15:07 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取所有画布模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-22 21:53:37 +08:00
|
|
|
|
public List<FlowCanvasDetails> GetAllCanvasModel() => [.. FlowCanvass.Values];
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 检查是否存在画布模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2025-07-04 15:46:29 +08:00
|
|
|
|
public bool IsExsitCanvas()
|
|
|
|
|
|
{
|
|
|
|
|
|
return FlowCanvass.Count > 0;
|
|
|
|
|
|
}
|
2025-07-08 14:22:41 +08:00
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 检查指定画布上是否存在节点模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="canvasGuid"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-07-04 15:46:29 +08:00
|
|
|
|
public bool IsExsitNodeOnCanvas(string canvasGuid)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!FlowCanvass.TryGetValue(canvasGuid, out var flowCanvasDetails))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return flowCanvasDetails.Nodes.Count > 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-22 21:53:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-07 20:40:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-07-08 14:22:41 +08:00
|
|
|
|
|
2025-07-07 20:40:24 +08:00
|
|
|
|
/* /// <summary>
|
|
|
|
|
|
/// 生成方法名称
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="flowNode"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
/// <exception cref="Exception"></exception>
|
|
|
|
|
|
private string GetNodeMethodName(IFlowNode flowNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
return $"FlowMethod_{flowNode.Guid.Remove('-')}";
|
|
|
|
|
|
|
|
|
|
|
|
if (flowNode.ControlType == NodeControlType.Action)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!flowLibraryService.TryGetMethodInfo(flowNode.MethodDetails.AssemblyName,
|
|
|
|
|
|
flowNode.MethodDetails.MethodName,
|
|
|
|
|
|
out var methodInfo))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception();
|
|
|
|
|
|
}
|
|
|
|
|
|
return $"FlowMethod_{nameof(NodeControlType.Action)}_{methodInfo.Name}";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (flowNode.ControlType == NodeControlType.Flipflop)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!flowLibraryService.TryGetMethodInfo(flowNode.MethodDetails.AssemblyName,
|
|
|
|
|
|
flowNode.MethodDetails.MethodName,
|
|
|
|
|
|
out var methodInfo))
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception();
|
|
|
|
|
|
}
|
|
|
|
|
|
return $"FlowMethod_{nameof(NodeControlType.Flipflop)}_{methodInfo.Name}";
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (flowNode.ControlType == NodeControlType.Script)
|
|
|
|
|
|
{
|
|
|
|
|
|
return $"FlowMethod_{flowNode.Guid.Remove('-')}";
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (flowNode.ControlType == NodeControlType.UI)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (flowNode.ControlType == NodeControlType.ExpCondition)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (flowNode.ControlType == NodeControlType.ExpOp)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("无法为该节点生成方法名称");
|
|
|
|
|
|
}
|
|
|
|
|
|
}*/
|