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;
namespace Serein.NodeFlow
{
///
/// 流程启动器
///
///
///
public class FlowStarter
{
public FlowStarter()
{
SereinIOC = new SereinIOC();
}
///
/// 流程运行状态
///
public enum RunState
{
///
/// 等待开始
///
NoStart,
///
/// 正在运行
///
Running,
///
/// 运行完成
///
Completion,
}
///
/// 控制触发器的结束
///
private NodeRunCts FlipFlopCts { get; set; } = null;
///
/// 运行状态
///
public RunState FlowState { get; private set; } = RunState.NoStart;
public RunState FlipFlopState { get; private set; } = RunState.NoStart;
///
/// 运行时的IOC容器
///
private ISereinIOC SereinIOC { get; } = null;
///
/// 结束运行时需要执行的方法
///
private Action ExitAction { get; set; } = null;
///
/// 运行的上下文
///
private IDynamicContext Context { get; set; } = null;
///
/// 开始运行
///
/// 起始节点
/// 运行环境
/// 环境中已加载的所有节点方法
/// 触发器节点
///
public async Task RunAsync(NodeModelBase startNode,
IFlowEnvironment env,
List runNodeMd,
List initMethods,
List loadingMethods,
List exitMethods,
List 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();
thisRuningMds.AddRange(runNodeMd);
thisRuningMds.AddRange(initMethods);
thisRuningMds.AddRange(loadingMethods);
thisRuningMds.AddRange(exitMethods);
// .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(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();
// 使用 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); // 启动触发器
});
}
///
/// 启动触发器
///
private async Task FlipflopExecute(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment flowEnvironment)
{
DynamicContext context = new DynamicContext(SereinIOC, flowEnvironment);
MethodDetails md = singleFlipFlopNode.MethodDetails;
var del = md.MethodDelegate;
try
{
//var func = md.ExplicitDatas.Length == 0 ? (Func