Files
serein-flow/NodeFlow/FlowStarter.cs
fengjiayi ef54c40d10 1.优化了平移缩放逻辑
2.优化了触发器的执行,优化了节点执行时的代码逻辑
3.优化了节点方法委托的参数获取
2024-09-18 22:57:47 +08:00

394 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Serein.Library.Api;
using Serein.Library.Core.NodeFlow;
using Serein.Library.Entity;
using Serein.Library.Enums;
using Serein.Library.Utils;
using Serein.Library.Web;
using Serein.NodeFlow.Base;
using Serein.NodeFlow.Model;
using System.ComponentModel.Design;
namespace Serein.NodeFlow
{
/// <summary>
/// 流程启动器
/// </summary>
/// <param name="serviceContainer"></param>
/// <param name="methodDetails"></param>
public class FlowStarter
{
public FlowStarter()
{
SereinIOC = new SereinIOC();
}
/// <summary>
/// 流程运行状态
/// </summary>
public enum RunState
{
/// <summary>
/// 等待开始
/// </summary>
NoStart,
/// <summary>
/// 正在运行
/// </summary>
Running,
/// <summary>
/// 运行完成
/// </summary>
Completion,
}
/// <summary>
/// 控制触发器的结束
/// </summary>
private NodeRunCts FlipFlopCts { get; set; } = null;
/// <summary>
/// 运行状态
/// </summary>
public RunState FlowState { get; private set; } = RunState.NoStart;
public RunState FlipFlopState { get; private set; } = RunState.NoStart;
/// <summary>
/// 运行时的IOC容器
/// </summary>
private ISereinIOC SereinIOC { get; } = null;
/// <summary>
/// 结束运行时需要执行的方法
/// </summary>
private Action ExitAction { get; set; } = null;
/// <summary>
/// 运行的上下文
/// </summary>
private IDynamicContext Context { get; set; } = null;
/// <summary>
/// 开始运行
/// </summary>
/// <param name="startNode">起始节点</param>
/// <param name="env">运行环境</param>
/// <param name="runNodeMd">环境中已加载的所有节点方法</param>
/// <param name="flipflopNodes">触发器节点</param>
/// <returns></returns>
public async Task RunAsync(NodeModelBase startNode,
IFlowEnvironment env,
List<MethodDetails> runNodeMd,
List<MethodDetails> initMethods,
List<MethodDetails> loadingMethods,
List<MethodDetails> exitMethods,
List<SingleFlipflopNode> flipflopNodes)
{
FlowState = RunState.Running; // 开始运行
if (startNode == null) {
FlowState = RunState.Completion; // 不存在起点,退出流程
return;
}
#region
// 判断使用哪一种流程上下文
var isNetFramework = true;
if (isNetFramework)
{
Context = new Serein.Library.Framework.NodeFlow.DynamicContext(SereinIOC, env);
}
else
{
Context = new Serein.Library.Core.NodeFlow.DynamicContext(SereinIOC, env);
}
#endregion
#region Ioc容器
// 清除节点使用的对象
var thisRuningMds = new List<MethodDetails>();
thisRuningMds.AddRange(runNodeMd.Where(md => md is not null));
thisRuningMds.AddRange(initMethods.Where(md => md is not null));
thisRuningMds.AddRange(loadingMethods.Where(md => md is not null));
thisRuningMds.AddRange(exitMethods.Where(md => md is not null));
// .AddRange(initMethods).AddRange(loadingMethods).a
foreach (var nodeMd in thisRuningMds)
{
nodeMd.ActingInstance = null;
}
SereinIOC.Reset(); // 开始运行时清空ioc中注册的实例
// 初始化ioc容器中的类型对象
foreach (var md in thisRuningMds)
{
if(md.ActingInstanceType != null)
{
SereinIOC.Register(md.ActingInstanceType);
}
}
SereinIOC.Build(); // 流程启动前的初始化
foreach (var md in thisRuningMds)
{
if (md.ActingInstanceType != null)
{
md.ActingInstance = SereinIOC.GetOrRegisterInstantiate(md.ActingInstanceType);
}
}
//foreach (var md in flipflopNodes.Select(it => it.MethodDetails).ToArray())
//{
// md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType);
//}
#endregion
#region 退
foreach (var md in initMethods) // 初始化
{
md.ActingInstance ??= Context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
}
foreach (var md in loadingMethods) // 加载
{
md.ActingInstance ??= Context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
}
foreach (var md in exitMethods) // 初始化
{
md.ActingInstance ??= Context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
}
#endregion
#region IOC容器
object?[]? args = [Context];
foreach (var md in initMethods) // 初始化
{
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
Context.SereinIoc.Build(); // 绑定初始化时注册的类型
foreach (var md in loadingMethods) // 加载
{
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
Context.SereinIoc.Build(); // 预防有人在加载时才注册类型,再绑定一次
#endregion
#region 退
ExitAction = () =>
{
SereinIOC.Run<WebServer>(web => {
web?.Stop();
});
foreach (MethodDetails? md in exitMethods)
{
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
if (Context != null && Context.NodeRunCts != null && !Context.NodeRunCts.IsCancellationRequested)
{
Context.NodeRunCts.Cancel();
}
if (FlipFlopCts != null && !FlipFlopCts.IsCancellationRequested)
{
FlipFlopCts.Cancel();
}
FlowState = RunState.Completion;
FlipFlopState = RunState.Completion;
};
#endregion
#region
try
{
if (flipflopNodes.Count > 0)
{
FlipFlopState = RunState.Running;
// 如果存在需要启动的触发器,则开始启动
FlipFlopCts = SereinIOC.GetOrRegisterInstantiate<NodeRunCts>();
// 使用 TaskCompletionSource 创建未启动的触发器任务
var tasks = flipflopNodes.Select(async node =>
{
await FlipflopExecute(node, env);
}).ToArray();
_ = Task.WhenAll(tasks);
}
await startNode.StartExecution(Context); // 从起始节点开始运行
// 等待结束
if (FlipFlopCts != null)
{
while (!FlipFlopCts.IsCancellationRequested)
{
await Task.Delay(100);
}
}
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
}
#endregion
}
public void AddFlipflopInRuning(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment flowEnvironment)
{
_ = Task.Run(async () =>
{
// 设置对象
singleFlipFlopNode.MethodDetails.ActingInstance = SereinIOC.GetOrRegisterInstantiate(singleFlipFlopNode.MethodDetails.ActingInstanceType);
await FlipflopExecute(singleFlipFlopNode, flowEnvironment); // 启动触发器
});
}
/// <summary>
/// 启动全局触发器
/// </summary>
private async Task FlipflopExecute(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment flowEnvironment)
{
var context = new DynamicContext(SereinIOC, flowEnvironment);
MethodDetails md = singleFlipFlopNode.MethodDetails;
var del = md.MethodDelegate;
// 设置方法执行的对象
if (md?.ActingInstance == null && md?.ActingInstanceType is not null)
{
md.ActingInstance ??= context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
}
// 设置委托对象
var func = md.ExplicitDatas.Length == 0 ?
(Func<object, object, Task<IFlipflopContext>>)del :
(Func<object, object[], Task<IFlipflopContext>>)del;
try
{
while (!FlipFlopCts.IsCancellationRequested)
{
object?[]? parameters = singleFlipFlopNode.GetParameters(context, singleFlipFlopNode.MethodDetails); // 启动全局触发器时获取入参参数
IFlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);// 首先开始等待触发器
_ = GlobalFlipflopExecute(singleFlipFlopNode, context);
}
//while (!FlipFlopCts.IsCancellationRequested)
//{
// if (singleFlipFlopNode.NotExitPreviousNode() == false)
// {
// break;
// }
// object?[]? parameters = singleFlipFlopNode.GetParameters(context, md);
// if (md.ActingInstance == null)
// {
// md.ActingInstance = context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
// }
// IFlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
// ConnectionType connection = flipflopContext.State.ToContentType();
// if (connection != ConnectionType.None)
// {
// singleFlipFlopNode.NextOrientation = connection;
// singleFlipFlopNode.FlowData = flipflopContext.Data;
// var tasks = singleFlipFlopNode.SuccessorNodes.Values
// .SelectMany(nodeList => nodeList)
// .Select(nextNode =>
// {
// var nextContext = new DynamicContext(SereinIOC, flowEnvironment);
// nextNode.PreviousNode = singleFlipFlopNode;
// return nextNode.StartExecution(nextContext); // 全局触发器收到信号,开始执行
// }).ToArray();
// await Task.WhenAll(tasks);
// }
// else
// {
// break;
// }
//}
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
}
}
public async Task GlobalFlipflopExecute(SingleFlipflopNode singleFlipFlopNode, IDynamicContext context)
{
if (FlipFlopCts.IsCancellationRequested)
{
return;
}
bool skip = true;
var cts = context.SereinIoc.GetOrRegisterInstantiate<CancellationTokenSource>();
Stack<NodeModelBase> stack = new Stack<NodeModelBase>();
stack.Push(singleFlipFlopNode);
ConnectionType connectionType = ConnectionType.IsSucceed;
while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环
{
// 从栈中弹出一个节点作为当前节点进行处理
var currentNode = stack.Pop();
// 设置方法执行的对象
if (currentNode.MethodDetails?.ActingInstance == null && currentNode.MethodDetails?.ActingInstanceType is not null)
{
currentNode.MethodDetails.ActingInstance ??= context.SereinIoc.GetOrRegisterInstantiate(currentNode.MethodDetails.ActingInstanceType);
}
// 首先执行上游分支
var upstreamNodes = currentNode.SuccessorNodes[ConnectionType.Upstream];
for (int i = upstreamNodes.Count - 1; i >= 0; i--)
{
upstreamNodes[i].PreviousNode = currentNode;
await upstreamNodes[i].StartExecution(context); // 执行上游分支
}
// 当前节点是已经触发了的全局触发器,所以跳过,难道每次都要判断一次?
if (skip)
{
skip = false;
}
else
{
// 判断是否为触发器节点,如果是,则开始等待。
if (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == NodeType.Flipflop)
{
currentNode.FlowData = await currentNode.ExecuteAsync(context); // 流程中遇到了触发器
}
else
{
currentNode.FlowData = currentNode.Execute(context); // 流程中正常执行
}
if (currentNode.NextOrientation == ConnectionType.None)
{
break; // 不再执行
}
connectionType = currentNode.NextOrientation;
}
// 获取下一分支
var nextNodes = currentNode.SuccessorNodes[connectionType];
// 将下一个节点集合中的所有节点逆序推入栈中
for (int i = nextNodes.Count - 1; i >= 0; i--)
{
nextNodes[i].PreviousNode = currentNode;
stack.Push(nextNodes[i]);
}
}
}
public void Exit()
{
ExitAction?.Invoke();
}
}
}