mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-03 06:46:35 +08:00
完成mvvm模式下,画布、节点编辑的基本重构
This commit is contained in:
@@ -5,6 +5,10 @@
|
||||
/// </summary>
|
||||
public static class EnvMsgTheme
|
||||
{
|
||||
/// <summary>
|
||||
/// 尝试保存项目
|
||||
/// </summary>
|
||||
public const string SaveProject = nameof(SaveProject);
|
||||
/// <summary>
|
||||
/// 获取远程环境信息
|
||||
/// </summary>
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 运行环境加载的画布集合
|
||||
/// </summary>
|
||||
private Dictionary<string, FlowCanvasModel> FlowCanvass { get; } = [];
|
||||
private Dictionary<string, FlowCanvasDetails> FlowCanvass { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 存放触发器节点(运行时全部调用)
|
||||
@@ -309,35 +309,35 @@ namespace Serein.NodeFlow.Env
|
||||
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
||||
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// 起始节点私有属性
|
||||
/// </summary>
|
||||
private NodeModelBase? _startNode = null;
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点私有属性
|
||||
/// </summary>
|
||||
private NodeModelBase? _startNode = null;
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点
|
||||
/// </summary>
|
||||
private NodeModelBase? StartNode
|
||||
{
|
||||
get
|
||||
{
|
||||
return _startNode;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_startNode is not null)
|
||||
{
|
||||
_startNode.IsStart = false;
|
||||
}
|
||||
value.IsStart = true;
|
||||
_startNode = value;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 起始节点
|
||||
/// </summary>
|
||||
private NodeModelBase? StartNode
|
||||
{
|
||||
get
|
||||
{
|
||||
return _startNode;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_startNode is not null)
|
||||
{
|
||||
_startNode.IsStart = false;
|
||||
}
|
||||
value.IsStart = true;
|
||||
_startNode = value;
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// 流程任务管理
|
||||
@@ -373,12 +373,11 @@ namespace Serein.NodeFlow.Env
|
||||
IOC.Reset();
|
||||
IOC.Register<IScriptFlowApi, ScriptFlowApi>(); // 注册脚本接口
|
||||
|
||||
var flowTaskOptions = new FlowWorkLibrary
|
||||
var flowTaskOptions = new FlowWorkOptions
|
||||
{
|
||||
|
||||
Environment = this,
|
||||
FlowContextPool = new ObjectPool<IDynamicContext>(() => new DynamicContext(this)),
|
||||
Nodes = NodeModels.Values.ToList(),
|
||||
//Nodes = NodeModels.Values.ToList(),
|
||||
AutoRegisterTypes = this.FlowLibraryManagement.GetaAutoRegisterType(),
|
||||
InitMds = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Init),
|
||||
LoadMds = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Loading),
|
||||
@@ -534,7 +533,8 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
public void SaveProject()
|
||||
{
|
||||
OnProjectSaving?.Invoke(new ProjectSavingEventArgs());
|
||||
var project = GetProjectInfoAsync().GetAwaiter().GetResult();
|
||||
OnProjectSaving?.Invoke(new ProjectSavingEventArgs(project));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -562,7 +562,7 @@ namespace Serein.NodeFlow.Env
|
||||
_ = Task.Run( async () =>
|
||||
{
|
||||
await LoadNodeInfosAsync(projectData.Nodes.ToList()); // 加载节点信息
|
||||
await SetStartNodeAsync("", projectData.StartNode); // 设置起始节点
|
||||
//await SetStartNodeAsync("", projectData.StartNode); // 设置起始节点
|
||||
});
|
||||
|
||||
}
|
||||
@@ -615,16 +615,17 @@ namespace Serein.NodeFlow.Env
|
||||
/// 序列化当前项目的依赖信息、节点信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<SereinProjectData> GetProjectInfoAsync()
|
||||
public async Task<SereinProjectData> GetProjectInfoAsync()
|
||||
{
|
||||
var projectData = new SereinProjectData()
|
||||
{
|
||||
Librarys = this.FlowLibraryManagement.GetAllLibraryInfo().ToArray(),
|
||||
Nodes = NodeModels.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
||||
StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
||||
Canvass = FlowCanvass.Values.Select(canvas => canvas.ToInfo()).ToArray(),
|
||||
//StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
||||
};
|
||||
|
||||
return Task.FromResult(projectData);
|
||||
return projectData;
|
||||
}
|
||||
|
||||
|
||||
@@ -776,22 +777,22 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="width">宽度</param>
|
||||
/// <param name="height">高度</param>
|
||||
/// <returns></returns>
|
||||
public Task<FlowCanvasInfo> CreateCanvasAsync(string canvasName, int width, int height)
|
||||
public async Task<FlowCanvasDetailsInfo> CreateCanvasAsync(string canvasName, int width, int height)
|
||||
{
|
||||
var model = new FlowCanvasModel(this)
|
||||
var model = new FlowCanvasDetails(this)
|
||||
{
|
||||
Guid = Guid.NewGuid().ToString(),
|
||||
Height = height,
|
||||
Name = !string.IsNullOrWhiteSpace(canvasName) ? canvasName : $"流程图 {_addCanvasCount++}",
|
||||
Width = height,
|
||||
Width = width,
|
||||
Name = !string.IsNullOrWhiteSpace(canvasName) ? canvasName : $"流程图{_addCanvasCount++}",
|
||||
};
|
||||
FlowCanvass.Add(model.Guid, model);
|
||||
UIContextOperation.Invoke(() =>
|
||||
await UIContextOperation.InvokeAsync(() =>
|
||||
{
|
||||
OnCanvasCreate.Invoke(new CanvasCreateEventArgs(model));
|
||||
});
|
||||
var info = model.ToInfo();
|
||||
return Task.FromResult(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -799,15 +800,29 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid">画布Guid</param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> RemoveCanvasAsync(string canvasGuid)
|
||||
public async Task<bool> RemoveCanvasAsync(string canvasGuid)
|
||||
{
|
||||
|
||||
if (!FlowCanvass.TryGetValue(canvasGuid, out var model))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
return false;
|
||||
}
|
||||
var count = NodeModels.Values.Count(node => node.CanvasGuid.Equals(canvasGuid));
|
||||
return Task.FromResult(count == 0);
|
||||
if(count > 0)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.WARN, "无法删除具有节点的画布");
|
||||
return false;
|
||||
}
|
||||
if (FlowCanvass.Remove(canvasGuid))
|
||||
{
|
||||
await UIContextOperation.InvokeAsync(() =>
|
||||
{
|
||||
OnCanvasRemove.Invoke(new CanvasRemoveEventArgs(canvasGuid));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -981,7 +996,7 @@ namespace Serein.NodeFlow.Env
|
||||
PositionOfUI position,
|
||||
MethodDetailsInfo? methodDetailsInfo = null)
|
||||
{
|
||||
if (!FlowCanvass.ContainsKey(canvasGuid))
|
||||
if (!TryGetCanvasModel(canvasGuid,out var cavnasModel))
|
||||
{
|
||||
return Task.FromResult<NodeInfo>(null);
|
||||
}
|
||||
@@ -1005,16 +1020,17 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
TryAddNode(nodeModel);
|
||||
nodeModel.Position = position;
|
||||
nodeModel.CanvasGuid = canvasGuid; // 设置所属于的画布
|
||||
nodeModel.Position = position; // 设置位置
|
||||
|
||||
// 通知UI更改
|
||||
UIContextOperation?.Invoke(() => OnNodeCreate?.Invoke(new NodeCreateEventArgs(canvasGuid, nodeModel, position)));
|
||||
|
||||
// 因为需要UI先布置了元素,才能通知UI变更特效
|
||||
// 如果不存在流程起始控件,默认设置为流程起始控件
|
||||
if (StartNode is null)
|
||||
if (cavnasModel.StartNode is null)
|
||||
{
|
||||
SetStartNode(canvasGuid, nodeModel);
|
||||
SetStartNode(cavnasModel, nodeModel);
|
||||
}
|
||||
var nodeInfo = nodeModel.ToInfo();
|
||||
return Task.FromResult(nodeInfo);
|
||||
@@ -1392,15 +1408,16 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 设置起点控件
|
||||
/// </summary>
|
||||
/// <param name="newNodeGuid"></param>
|
||||
/// <param name="canvasGuid">画布</param>
|
||||
/// <param name="newNodeGuid">节点Guid</param>
|
||||
public Task<string> SetStartNodeAsync(string canvasGuid, string newNodeGuid)
|
||||
{
|
||||
if (!FlowCanvass.ContainsKey(canvasGuid) || !TryGetNodeModel(newNodeGuid, out var newStartNodeModel))
|
||||
if (!TryGetCanvasModel(canvasGuid, out var canvasModel) || !TryGetNodeModel(newNodeGuid, out var newStartNodeModel))
|
||||
{
|
||||
return Task.FromResult(StartNode?.Guid ?? string.Empty);
|
||||
return Task.FromResult(canvasModel.StartNode ?? string.Empty);
|
||||
}
|
||||
SetStartNode(canvasGuid, newStartNodeModel);
|
||||
return Task.FromResult(StartNode?.Guid ?? string.Empty);
|
||||
SetStartNode(canvasModel, newStartNodeModel);
|
||||
return Task.FromResult(canvasModel.StartNode ?? string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1512,9 +1529,25 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从Guid获取画布
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <returns>节点Model</returns>
|
||||
/// <exception cref="ArgumentNullException">无法获取节点、Guid/节点为null时报错</exception>
|
||||
public bool TryGetCanvasModel(string nodeGuid, out FlowCanvasDetails canvasDetails)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nodeGuid))
|
||||
{
|
||||
canvasDetails = null;
|
||||
return false;
|
||||
}
|
||||
return FlowCanvass.TryGetValue(nodeGuid, out canvasDetails) && canvasDetails is not null;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Guid 转 NodeModel
|
||||
/// 从Guid获取节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <returns>节点Model</returns>
|
||||
@@ -1913,15 +1946,11 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
/// <param name="newStartNode"></param>
|
||||
/// <param name="oldStartNode"></param>
|
||||
private void SetStartNode(string canvasGuid, NodeModelBase newStartNode)
|
||||
private void SetStartNode(FlowCanvasDetails cavnasModel, NodeModelBase newStartNode)
|
||||
{
|
||||
if (!FlowCanvass.ContainsKey(canvasGuid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var oldNodeGuid = StartNode?.Guid;
|
||||
StartNode = newStartNode;
|
||||
UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(canvasGuid, oldNodeGuid, StartNode.Guid)));
|
||||
var oldNodeGuid = cavnasModel.StartNode;
|
||||
cavnasModel.StartNode = newStartNode.Guid;
|
||||
UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(cavnasModel.Guid, oldNodeGuid, cavnasModel.StartNode)));
|
||||
|
||||
//if (OperatingSystem.IsWindows())
|
||||
//{
|
||||
|
||||
@@ -238,7 +238,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="width">宽度</param>
|
||||
/// <param name="height">高度</param>
|
||||
/// <returns></returns>
|
||||
public async Task<FlowCanvasInfo> CreateCanvasAsync(string canvasName, int width, int height)
|
||||
public async Task<FlowCanvasDetailsInfo> CreateCanvasAsync(string canvasName, int width, int height)
|
||||
{
|
||||
return await currentFlowEnvironment.CreateCanvasAsync(canvasName, width, height);
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.CreateCanvas, IsReturnValue = false)]
|
||||
public void CreateCanvas([UseMsgId] string msgId, [UseData] FlowCanvasInfo canvasInfo)
|
||||
public void CreateCanvas([UseMsgId] string msgId, [UseData] FlowCanvasDetailsInfo canvasInfo)
|
||||
{
|
||||
_ = remoteFlowEnvironment.InvokeTriggerAsync(msgId, canvasInfo);
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
|
||||
[AutoSocketHandle(ThemeValue = EnvMsgTheme.CreateCanvas, IsReturnValue = false)]
|
||||
public async Task<FlowCanvasInfo> CreateCanvas(string canvasName, int width, int height)
|
||||
public async Task<FlowCanvasDetailsInfo> CreateCanvas(string canvasName, int width, int height)
|
||||
{
|
||||
var canvasInfo = await environment.CreateCanvasAsync(canvasName, width, height); // 监听到客户端创建节点的请求
|
||||
return canvasInfo;
|
||||
|
||||
@@ -131,11 +131,28 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存项目
|
||||
/// 远程环境下保存项目
|
||||
/// </summary>
|
||||
public void SaveProject()
|
||||
{
|
||||
OnProjectSaving?.Invoke(new ProjectSavingEventArgs());
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
// 保存项目
|
||||
var result = await msgClient.SendAndWaitDataAsync<SereinProjectData>(EnvMsgTheme.SaveProject);
|
||||
if (result is not null)
|
||||
{
|
||||
OnProjectSaving?.Invoke(new ProjectSavingEventArgs(result));
|
||||
}
|
||||
});
|
||||
|
||||
// 获取远程环境
|
||||
//var projectData = new SereinProjectData()
|
||||
//{
|
||||
// Librarys = this.FlowLibraryManagement.GetAllLibraryInfo().ToArray(),
|
||||
// Nodes = NodeModels.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
||||
// StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
||||
//};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -167,14 +184,26 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
#endregion
|
||||
|
||||
var nodeInfos = flowEnvInfo.Project.Nodes.ToList();
|
||||
LoadNodeInfos(nodeInfos); // 加载节点
|
||||
|
||||
var canvasGuid = nodeInfos.FirstOrDefault(item => item.Guid == flowEnvInfo.Project.StartNode)?.CanvasGuid;
|
||||
if (!string.IsNullOrEmpty(canvasGuid))
|
||||
// 加载画布
|
||||
foreach (var info in flowEnvInfo.Project.Canvass)
|
||||
{
|
||||
_ = SetStartNodeAsync(canvasGuid, flowEnvInfo.Project.StartNode); // 设置流程起点
|
||||
var canvasModel = new FlowCanvasDetails(this);
|
||||
canvasModel.LoadInfo(info);
|
||||
var e = new CanvasCreateEventArgs(canvasModel);
|
||||
OnCanvasCreate?.Invoke(e);
|
||||
}
|
||||
|
||||
// 加载节点
|
||||
var nodeInfos = flowEnvInfo.Project.Nodes.ToList();
|
||||
LoadNodeInfos(nodeInfos);
|
||||
|
||||
// 设置每个画布的起始节点
|
||||
foreach (var info in flowEnvInfo.Project.Canvass)
|
||||
{
|
||||
_ = SetStartNodeAsync(info.Guid, info.StartNode); // 设置流程起点
|
||||
|
||||
}
|
||||
|
||||
UIContextOperation?.Invoke(() =>
|
||||
{
|
||||
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs()); // 加载完成
|
||||
@@ -427,9 +456,9 @@ namespace Serein.NodeFlow.Env
|
||||
/// <param name="width">宽度</param>
|
||||
/// <param name="height">高度</param>
|
||||
/// <returns></returns>
|
||||
public async Task<FlowCanvasInfo> CreateCanvasAsync(string canvasName, int width, int height)
|
||||
public async Task<FlowCanvasDetailsInfo> CreateCanvasAsync(string canvasName, int width, int height)
|
||||
{
|
||||
var info = await msgClient.SendAndWaitDataAsync<FlowCanvasInfo>(EnvMsgTheme.CreateCanvas, new
|
||||
var info = await msgClient.SendAndWaitDataAsync<FlowCanvasDetailsInfo>(EnvMsgTheme.CreateCanvas, new
|
||||
{
|
||||
canvasName,
|
||||
width,
|
||||
@@ -437,7 +466,7 @@ namespace Serein.NodeFlow.Env
|
||||
});
|
||||
if (info is not null)
|
||||
{
|
||||
var model = new FlowCanvasModel(this)
|
||||
var model = new FlowCanvasDetails(this)
|
||||
{
|
||||
Guid = info.Guid,
|
||||
Height = info.Height,
|
||||
@@ -506,6 +535,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 设置远程环境的流程起点节点
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid">节点画布</param>
|
||||
/// <param name="nodeGuid">尝试设置为起始节点的节点Guid</param>
|
||||
/// <returns>被设置为起始节点的Guid</returns>
|
||||
public async Task<string> SetStartNodeAsync(string canvasGuid, string nodeGuid)
|
||||
|
||||
@@ -6,6 +6,7 @@ using Serein.NodeFlow.Model;
|
||||
using Serein.NodeFlow.Tool;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks.Dataflow;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Serein.NodeFlow
|
||||
@@ -20,25 +21,24 @@ namespace Serein.NodeFlow
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<SingleFlipflopNode, CancellationTokenSource> dictGlobalFlipflop = [];
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 结束运行时需要执行的方法
|
||||
/// </summary>
|
||||
private Func<Task>? ExitAction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化选项
|
||||
/// </summary>
|
||||
public FlowWorkLibrary WorkLibrary { get; }
|
||||
public FlowWorkOptions WorkOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 流程任务管理
|
||||
/// </summary>
|
||||
/// <param name="library"></param>
|
||||
public FlowWorkManagement(FlowWorkLibrary library)
|
||||
/// <param name="options"></param>
|
||||
public FlowWorkManagement(FlowWorkOptions options)
|
||||
{
|
||||
WorkLibrary = library;
|
||||
WorkOptions = options;
|
||||
|
||||
}
|
||||
|
||||
@@ -48,43 +48,83 @@ namespace Serein.NodeFlow
|
||||
/// <returns></returns>
|
||||
public async Task<bool> RunAsync(CancellationToken token)
|
||||
{
|
||||
NodeModelBase? startNode = WorkLibrary.Nodes.FirstOrDefault(node => node.IsStart);
|
||||
if (startNode is null)
|
||||
#region 注册所有节点所属的类的类型,如果注册失败则退出
|
||||
List<NodeModelBase> nodes = new List<NodeModelBase>();
|
||||
foreach (var item in WorkOptions.Flows.Values)
|
||||
{
|
||||
var temp = item.GetNodes();
|
||||
nodes.AddRange(temp);
|
||||
}
|
||||
if (!RegisterAllType(nodes))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 调用所有流程类的Init、Load事件
|
||||
|
||||
if (!RegisterAllType())
|
||||
{
|
||||
return false;
|
||||
};
|
||||
var initState = await TryInit();
|
||||
if (!initState)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
}
|
||||
;
|
||||
var loadState = await TryLoadAsync();
|
||||
if (!loadState)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
var task = CallFlipflopNode();
|
||||
await CallStartNode(startNode);
|
||||
await task;
|
||||
}
|
||||
;
|
||||
#endregion
|
||||
|
||||
// 开始调用流程
|
||||
foreach (var kvp in WorkOptions.Flows)
|
||||
{
|
||||
var guid = kvp.Key;
|
||||
var flow = kvp.Value;
|
||||
var flowNodes = flow.GetNodes();
|
||||
|
||||
// 找到流程的起始节点,开始运行
|
||||
NodeModelBase? startNode = flowNodes.FirstOrDefault(node => node.IsStart);
|
||||
if (startNode is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// 是否后台运行当前画布流程
|
||||
if (flow.IsTaskAsync)
|
||||
{
|
||||
_ = Task.Run(async () => await CallStartNode(startNode));
|
||||
}
|
||||
else
|
||||
{
|
||||
await CallStartNode(startNode);
|
||||
}
|
||||
var flipflopTasks = CallFlipflopNode(flow); // 获取所有触发器异步任务
|
||||
_ = Task.Run(async () => await flipflopTasks); // 后台调用流程中的触发器
|
||||
}
|
||||
|
||||
// 等待流程运行完成
|
||||
await CallExit();
|
||||
return true;
|
||||
}
|
||||
|
||||
#region 初始化
|
||||
private bool RegisterAllType()
|
||||
/// <summary>
|
||||
/// 初始化节点所需的所有类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool RegisterAllType(List<NodeModelBase> nodes)
|
||||
{
|
||||
var env = WorkLibrary.Environment;
|
||||
var nodeMds = WorkLibrary.Nodes.Select(item => item.MethodDetails).ToList(); // 获取环境中所有节点的方法信息
|
||||
var env = WorkOptions.Environment;
|
||||
|
||||
|
||||
|
||||
var nodeMds = nodes.Select(item => item.MethodDetails).ToList(); // 获取环境中所有节点的方法信息
|
||||
var allMds = new List<MethodDetails>();
|
||||
allMds.AddRange(nodeMds.Where(md => md?.ActingInstanceType is not null));
|
||||
allMds.AddRange(WorkLibrary.InitMds.Where(md => md?.ActingInstanceType is not null));
|
||||
allMds.AddRange(WorkLibrary.LoadMds.Where(md => md?.ActingInstanceType is not null));
|
||||
allMds.AddRange(WorkLibrary.ExitMds.Where(md => md?.ActingInstanceType is not null));
|
||||
allMds.AddRange(WorkOptions.InitMds.Where(md => md?.ActingInstanceType is not null));
|
||||
allMds.AddRange(WorkOptions.LoadMds.Where(md => md?.ActingInstanceType is not null));
|
||||
allMds.AddRange(WorkOptions.ExitMds.Where(md => md?.ActingInstanceType is not null));
|
||||
var isSuccessful = true;
|
||||
foreach (var md in allMds)
|
||||
{
|
||||
@@ -114,10 +154,10 @@ namespace Serein.NodeFlow
|
||||
|
||||
private async Task<bool> TryInit()
|
||||
{
|
||||
var env = WorkLibrary.Environment;
|
||||
var initMds = WorkLibrary.InitMds;
|
||||
var pool = WorkLibrary.FlowContextPool;
|
||||
var ioc = WorkLibrary.Environment.IOC;
|
||||
var env = WorkOptions.Environment;
|
||||
var initMds = WorkOptions.InitMds;
|
||||
var pool = WorkOptions.FlowContextPool;
|
||||
var ioc = WorkOptions.Environment.IOC;
|
||||
foreach (var md in initMds) // 初始化
|
||||
{
|
||||
if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd)) // 流程运行初始化
|
||||
@@ -136,10 +176,10 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
private async Task<bool> TryLoadAsync()
|
||||
{
|
||||
var env = WorkLibrary.Environment;
|
||||
var loadMds = WorkLibrary.LoadMds;
|
||||
var pool = WorkLibrary.FlowContextPool;
|
||||
var ioc = WorkLibrary.Environment.IOC;
|
||||
var env = WorkOptions.Environment;
|
||||
var loadMds = WorkOptions.LoadMds;
|
||||
var pool = WorkOptions.FlowContextPool;
|
||||
var ioc = WorkOptions.Environment.IOC;
|
||||
foreach (var md in loadMds) // 加载时
|
||||
{
|
||||
if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd)) // 流程运行初始化
|
||||
@@ -159,10 +199,10 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
private async Task<bool> CallExit()
|
||||
{
|
||||
var env = WorkLibrary.Environment;
|
||||
var mds = WorkLibrary.ExitMds;
|
||||
var pool = WorkLibrary.FlowContextPool;
|
||||
var ioc = WorkLibrary.Environment.IOC;
|
||||
var env = WorkOptions.Environment;
|
||||
var mds = WorkOptions.ExitMds;
|
||||
var pool = WorkOptions.FlowContextPool;
|
||||
var ioc = WorkOptions.Environment.IOC;
|
||||
|
||||
ioc.Run<FlowInterruptTool>(fit => fit.CancelAllTrigger());// 取消所有中断
|
||||
foreach (var md in mds) // 结束时
|
||||
@@ -186,10 +226,10 @@ namespace Serein.NodeFlow
|
||||
return isSuccessful;
|
||||
}
|
||||
|
||||
private Task CallFlipflopNode()
|
||||
private Task CallFlipflopNode(FlowTask flow)
|
||||
{
|
||||
var env = WorkLibrary.Environment;
|
||||
var flipflopNodes = WorkLibrary.Nodes.Where(item => item is SingleFlipflopNode node
|
||||
var env = WorkOptions.Environment;
|
||||
var flipflopNodes = flow.GetNodes().Where(item => item is SingleFlipflopNode node
|
||||
&& !node.IsStart
|
||||
&& node.DebugSetting.IsEnable
|
||||
&& node.NotExitPreviousNode())
|
||||
@@ -206,10 +246,16 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从某一个节点开始执行
|
||||
/// </summary>
|
||||
/// <param name="startNode"></param>
|
||||
/// <returns></returns>
|
||||
private async Task CallStartNode(NodeModelBase startNode)
|
||||
{
|
||||
var pool = WorkLibrary.FlowContextPool;
|
||||
var token = WorkLibrary.CancellationTokenSource.Token;
|
||||
var pool = WorkOptions.FlowContextPool;
|
||||
var token = WorkOptions.CancellationTokenSource.Token;
|
||||
var context = pool.Allocate();
|
||||
await startNode.StartFlowAsync(context, token);
|
||||
context.Exit();
|
||||
@@ -227,9 +273,9 @@ namespace Serein.NodeFlow
|
||||
/// <returns></returns>
|
||||
public async Task StartFlowInSelectNodeAsync(IFlowEnvironment env, NodeModelBase startNode)
|
||||
{
|
||||
var pool = WorkLibrary.FlowContextPool;
|
||||
var pool = WorkOptions.FlowContextPool;
|
||||
var context = pool.Allocate();
|
||||
var token = WorkLibrary.CancellationTokenSource.Token;
|
||||
var token = WorkOptions.CancellationTokenSource.Token;
|
||||
await startNode.StartFlowAsync(context, token); // 开始运行时从选定节点开始运行
|
||||
context.Reset();
|
||||
pool.Free(context);
|
||||
@@ -294,7 +340,7 @@ namespace Serein.NodeFlow
|
||||
CancellationToken singleToken)
|
||||
{
|
||||
|
||||
var pool = WorkLibrary.FlowContextPool;
|
||||
var pool = WorkOptions.FlowContextPool;
|
||||
while (!singleToken.IsCancellationRequested && !singleToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -9,10 +9,29 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow
|
||||
{
|
||||
|
||||
public class FlowTask
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否异步启动流程
|
||||
/// </summary>
|
||||
public bool IsTaskAsync { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 流程起始节点
|
||||
/// </summary>
|
||||
public Func<NodeModelBase> GetStartNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前画布流程的所有节点
|
||||
/// </summary>
|
||||
public Func<List<NodeModelBase>> GetNodes { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节点任务执行依赖
|
||||
/// </summary>
|
||||
public class FlowWorkLibrary()
|
||||
public class FlowWorkOptions()
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程运行环境
|
||||
@@ -29,14 +48,21 @@ namespace Serein.NodeFlow
|
||||
/// </summary>
|
||||
public Serein.Library.Utils.ObjectPool<IDynamicContext> FlowContextPool { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 每个画布需要启用的节点
|
||||
/// </summary>
|
||||
public Dictionary<string, FlowTask> Flows { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前任务加载的所有节点
|
||||
/// </summary>
|
||||
public List<NodeModelBase> Nodes { get; set; }// = nodes;
|
||||
//public List<NodeModelBase> Nodes { get; set; }// = nodes;
|
||||
|
||||
/// <summary>
|
||||
/// 需要注册的类型
|
||||
/// </summary>
|
||||
public Dictionary<RegisterSequence, List<Type>> AutoRegisterTypes { get; set; } //= autoRegisterTypes;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化时需要的方法
|
||||
/// </summary>
|
||||
Reference in New Issue
Block a user