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>>)del : (Func>>)del; var func = md.ExplicitDatas.Length == 0 ? (Func>)del : (Func>)del; while (!FlipFlopCts.IsCancellationRequested) // 循环中直到栈为空才会退出 { if(singleFlipFlopNode.NotExitPreviousNode() == false) { // 存在上级节点时,退出触发器 break; } object?[]? parameters = singleFlipFlopNode.GetParameters(context, md); // 调用委托并获取结果 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 upstreamNodeTasks = singleFlipFlopNode.SuccessorNodes[ConnectionType.Upstream].Select(nextNode => { var context = new DynamicContext(SereinIOC, flowEnvironment); nextNode.PreviousNode = singleFlipFlopNode; return nextNode.StartExecution(context); }).ToArray(); var tmpTasks = singleFlipFlopNode.SuccessorNodes[connection].Select(nextNode => { var context = new DynamicContext(SereinIOC,flowEnvironment); nextNode.PreviousNode = singleFlipFlopNode; return nextNode.StartExecution(context); }).ToArray(); Task[] tasks = [..upstreamNodeTasks, .. tmpTasks]; Task.WaitAll(tasks); } else { break; } } } catch (Exception ex) { await Console.Out.WriteLineAsync(ex.ToString()); } } public void Exit() { ExitAction?.Invoke(); } } }