using Serein.Library.Api; using Serein.Library.Utils; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Serein.Library { /// /// 流程调用树,管理所有的调用节点 /// public class FlowCallTree : IFlowCallTree { private readonly SortedDictionary _callNodes = new SortedDictionary(); /// /// 索引器,允许通过字符串索引访问CallNode /// /// /// public CallNode this[string index] { get { _callNodes.TryGetValue(index, out CallNode callNode); return callNode; } set { // 设置指定索引的值 _callNodes.Add(index, value); } } /// /// 添加一个调用节点到流程调用树中 /// /// /// public void AddCallNode(string nodeGuid, Action action) { var node = new CallNode(nodeGuid, action); _callNodes[nodeGuid] = node; } /// /// 添加一个调用节点到流程调用树中,使用异步函数 /// /// /// public void AddCallNode(string nodeGuid, Func func) { var node = new CallNode(nodeGuid, func); _callNodes[nodeGuid] = node; } /// /// 获取指定Key的CallNode,如果不存在则返回null /// /// /// public CallNode Get(string key) { return _callNodes.TryGetValue(key, out CallNode callNode) ? callNode : null; } } /// /// 调用节点,代表一个流程中的调用点,可以是一个Action或一个异步函数。 /// public class CallNode { private Func taskFunc; private Action action; /// /// 创建一个新的调用节点,使用指定的节点Guid。 /// /// public CallNode(string nodeGuid) { Guid = nodeGuid; Init(); } /// /// 创建一个新的调用节点,使用指定的节点Guid和Action。 /// /// /// public CallNode(string nodeGuid, Action action) { Guid = nodeGuid; this.action = action; Init(); } /// /// 创建一个新的调用节点,使用指定的节点Guid和异步函数。 /// /// /// public CallNode(string nodeGuid, Func func) { Guid = nodeGuid; this.taskFunc = func; Init(); } /// /// 初始化调用节点,设置默认的子节点和后继节点字典。 /// private void Init() { //PreviousNodes = new Dictionary>(); SuccessorNodes = new Dictionary>(); foreach (ConnectionInvokeType ctType in NodeStaticConfig.ConnectionTypes) { //PreviousNodes[ctType] = new List(); SuccessorNodes[ctType] = new List(); } } private enum ActionType { Action, Task, } private ActionType actionType = ActionType.Action; /// /// 设置调用节点的Action,表示该节点执行一个同步操作。 /// /// public void SetAction(Action action) { this.action = action; actionType = ActionType.Action; } /// /// 设置调用节点的异步函数,表示该节点执行一个异步操作。 /// /// public void SetAction(Func taskFunc) { this.taskFunc = taskFunc; actionType = ActionType.Task; } /// /// 对应的节点 /// public string Guid { get; } #if false /// /// 不同分支的父节点(流程调用) /// public Dictionary> PreviousNodes { get; private set; } #endif /// /// 不同分支的子节点(流程调用) /// public Dictionary> SuccessorNodes { get; private set; } /// /// 子节点数组,分为四个分支:上游、成功、失败、错误,每个分支最多支持16个子节点。 /// public CallNode[][] ChildNodes { get; private set; } = new CallNode[][] { new CallNode[MaxChildNodeCount], new CallNode[MaxChildNodeCount], new CallNode[MaxChildNodeCount], new CallNode[MaxChildNodeCount] }; private const int MaxChildNodeCount = 16; // 每个分支最多支持16个子节点 /// /// 获取指定类型的子节点数量。 /// /// /// public int GetCount(ConnectionInvokeType type) { if (type == ConnectionInvokeType.Upstream) return UpstreamNodeCount; if (type == ConnectionInvokeType.IsSucceed) return IsSuccessorNodeCount; if (type == ConnectionInvokeType.IsFail) return IsFailNodeCount; if (type == ConnectionInvokeType.IsError) return IsErrorNodeCount; return 0; } /// /// 获取当前节点的子节点数量。 /// public int UpstreamNodeCount { get; private set; } = 0; /// /// 获取当前节点的成功后继子节点数量。 /// public int IsSuccessorNodeCount { get; private set; } = 0; /// /// 获取当前节点的失败后继子节点数量。 /// public int IsFailNodeCount { get; private set; } = 0; /// /// 获取当前节点的错误后继子节点数量。 /// public int IsErrorNodeCount { get; private set; } = 0; /// /// 添加一个上游子节点到当前节点。 /// /// /// public CallNode AddChildNodeUpstream(CallNode callNode) { var connectionInvokeType = ConnectionInvokeType.Upstream; ChildNodes[(int)connectionInvokeType][UpstreamNodeCount++] = callNode; SuccessorNodes[connectionInvokeType].Add(callNode); return this; } /// /// 添加一个成功后继子节点到当前节点。 /// /// /// public CallNode AddChildNodeSucceed(CallNode callNode) { ChildNodes[0][UpstreamNodeCount++] = callNode; var connectionInvokeType = ConnectionInvokeType.IsSucceed; ChildNodes[(int)connectionInvokeType][IsSuccessorNodeCount++] = callNode; SuccessorNodes[connectionInvokeType].Add(callNode); return this; } /// /// 添加一个失败后继子节点到当前节点。 /// /// /// public CallNode AddChildNodeFail(CallNode callNode) { var connectionInvokeType = ConnectionInvokeType.IsFail; ChildNodes[(int)connectionInvokeType][IsFailNodeCount++] = callNode; SuccessorNodes[connectionInvokeType].Add(callNode); return this; } /// /// 添加一个错误后继子节点到当前节点。 /// /// /// public CallNode AddChildNodeError(CallNode callNode) { var connectionInvokeType = ConnectionInvokeType.IsError; ChildNodes[(int)connectionInvokeType][IsErrorNodeCount++] = callNode; SuccessorNodes[connectionInvokeType].Add(callNode); return this; } /// /// 调用 /// /// /// /// /// public async Task InvokeAsync(IFlowContext context, CancellationToken token) { if (token.IsCancellationRequested) { return; } if (actionType == ActionType.Action) { action.Invoke(context); } else if (actionType == ActionType.Task) { await taskFunc.Invoke(context); } else { throw new InvalidOperationException($"生成了错误的CallNode。【{Guid}】"); } } private static readonly ObjectPool> _stackPool = new ObjectPool>(() => new Stack()); /// /// 开始执行 /// /// /// 流程运行 /// public async Task StartFlowAsync(IFlowContext context, CancellationToken token) { var stack = _stackPool.Allocate(); stack.Push(this); while (true) { if (token.IsCancellationRequested) { throw new Exception($"流程执行被取消,未能获取到流程结果。"); } #region 执行相关 // 从栈中弹出一个节点作为当前节点进行处理 var currentNode = stack.Pop(); context.NextOrientation = ConnectionInvokeType.None; // 重置上下文状态 FlowResult flowResult = null; try { context.NextOrientation = ConnectionInvokeType.IsSucceed; // 默认执行成功 await currentNode.InvokeAsync(context, token); } catch (Exception ex) { flowResult = FlowResult.Fail(currentNode.Guid, context, ex.Message); context.Env.WriteLine(InfoType.ERROR, $"节点[{currentNode}]异常:" + ex); context.NextOrientation = ConnectionInvokeType.IsError; context.ExceptionOfRuning = ex; } #endregion #region 执行完成时更新栈 // 首先将指定类别后继分支的所有节点逆序推入栈中 var nextNodes = currentNode.SuccessorNodes[context.NextOrientation]; for (int index = nextNodes.Count - 1; index >= 0; index--) { var node = nextNodes[index]; context.SetPreviousNode(node.Guid, currentNode.Guid); stack.Push(node); } // 然后将指上游分支的所有节点逆序推入栈中 var upstreamNodes = currentNode.SuccessorNodes[ConnectionInvokeType.Upstream]; for (int index = upstreamNodes.Count - 1; index >= 0; index--) { var node = upstreamNodes[index]; context.SetPreviousNode(node.Guid, currentNode.Guid); stack.Push(node); } #endregion #region 执行完成后检查 if (stack.Count == 0) { _stackPool.Free(stack); flowResult = context.GetFlowData(currentNode.Guid); return flowResult; // 说明流程到了终点 } if (context.RunState == RunState.Completion) { _stackPool.Free(stack); context.Env.WriteLine(InfoType.INFO, $"流程执行到节点[{currentNode.Guid}]时提前结束,将返回当前执行结果。"); flowResult = context.GetFlowData(currentNode.Guid); return flowResult; // 流程执行完成,返回结果 } if (token.IsCancellationRequested) { _stackPool.Free(stack); throw new Exception($"流程执行到节点[{currentNode.Guid}]时被取消,未能获取到流程结果。"); } #endregion } } } /// /// 流程调用树接口,提供获取CallNode的方法。 /// public interface IFlowCallTree { /// /// 获取指定Key的CallNode,如果不存在则返回null。 /// /// /// CallNode Get(string key); } /// /// 轻量级流程控制器 /// public class LightweightFlowControl : IFlowControl { private readonly IFlowCallTree flowCallTree; private readonly IFlowEnvironment flowEnvironment; /// /// 轻量级流程上下文池,使用对象池模式来管理流程上下文的创建和回收。 /// public static Serein.Library.Utils.ObjectPool FlowContextPool { get; set; } /// /// 单例IOC容器,用于依赖注入和服务定位。 /// public ISereinIOC IOC => throw new NotImplementedException(); /// /// 轻量级流程控制器构造函数,接受流程调用树和流程环境作为参数。 /// /// /// public LightweightFlowControl(IFlowCallTree flowCallTree, IFlowEnvironment flowEnvironment) { this.flowCallTree = flowCallTree; this.flowEnvironment = flowEnvironment; FlowContextPool = new Utils.ObjectPool(() => { return new FlowContext(flowEnvironment); }); } /// public Task InvokeAsync(string apiGuid, Dictionary dict) { throw new NotImplementedException(); } /// public Task InvokeAsync(string apiGuid, Dictionary dict) { throw new NotImplementedException(); } //private readonly DefaultObjectPool _stackPool = new DefaultObjectPool(new DynamicContext(this)); /// public async Task StartFlowAsync(string startNodeGuid) { IFlowContext context = Serein.Library.LightweightFlowControl.FlowContextPool.Allocate(); CancellationTokenSource cts = new CancellationTokenSource(); FlowResult flowResult; #if DEBUG flowResult = await BenchmarkHelpers.BenchmarkAsync(async () => { var node = flowCallTree.Get(startNodeGuid); var flowResult = await node.StartFlowAsync(context, cts.Token); return flowResult; }); #else var node = flowCallTree.Get(startNodeGuid); try { flowResult = await node.StartFlowAsync(context, cts.Token); } catch (global::System.Exception) { throw; } finally { context.Reset(); FlowContextPool.Free(context); } #endif cts?.Cancel(); cts?.Dispose(); if (flowResult.Value is TResult result) { return result; } else if (flowResult is FlowResult && flowResult is TResult result2) { return result2; } else { throw new ArgumentNullException($"类型转换失败,流程返回数据与泛型不匹配,当前返回类型为[{flowResult.Value.GetType().FullName}]。"); } } /// public Task StartFlowAsync(string[] canvasGuids) { throw new NotImplementedException(); } /// public Task ExitFlowAsync() { throw new NotImplementedException(); } #region 无须实现 /// public void ActivateFlipflopNode(string nodeGuid) { throw new NotImplementedException(); } /// public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType) { throw new NotImplementedException(); } /// public void TerminateFlipflopNode(string nodeGuid) { throw new NotImplementedException(); } /// public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type) { throw new NotImplementedException(); } /// public void UseExternalIOC(ISereinIOC ioc) { throw new NotImplementedException(); } /// public void UseExternalIOC(ISereinIOC ioc, Action setDefultMemberOnReset = null) { throw new NotImplementedException(); } #endregion } /// /// 轻量级流程环境事件实现 /// public class LightweightFlowEnvironmentEvent : IFlowEnvironmentEvent { /// public event LoadDllHandler DllLoad; /// public event ProjectLoadedHandler ProjectLoaded; /// public event ProjectSavingHandler ProjectSaving; /// public event NodeConnectChangeHandler NodeConnectChanged; /// public event CanvasCreateHandler CanvasCreated; /// public event CanvasRemoveHandler CanvasRemoved; /// public event NodeCreateHandler NodeCreated; /// public event NodeRemoveHandler NodeRemoved; /// public event NodePlaceHandler NodePlace; /// public event NodeTakeOutHandler NodeTakeOut; /// public event StartNodeChangeHandler StartNodeChanged; /// public event FlowRunCompleteHandler FlowRunComplete; /// public event MonitorObjectChangeHandler MonitorObjectChanged; /// public event NodeInterruptStateChangeHandler NodeInterruptStateChanged; /// public event ExpInterruptTriggerHandler InterruptTriggered; /// public event IOCMembersChangedHandler IOCMembersChanged; /// public event NodeLocatedHandler NodeLocated; /// public event EnvOutHandler EnvOutput; /// public void OnDllLoad(LoadDllEventArgs eventArgs) { DllLoad?.Invoke(eventArgs); } /// public void OnProjectLoaded(ProjectLoadedEventArgs eventArgs) { ProjectLoaded?.Invoke(eventArgs); } /// public void OnProjectSaving(ProjectSavingEventArgs eventArgs) { ProjectSaving?.Invoke(eventArgs); } /// public void OnNodeConnectChanged(NodeConnectChangeEventArgs eventArgs) { NodeConnectChanged?.Invoke(eventArgs); } /// public void OnCanvasCreated(CanvasCreateEventArgs eventArgs) { CanvasCreated?.Invoke(eventArgs); } /// public void OnCanvasRemoved(CanvasRemoveEventArgs eventArgs) { CanvasRemoved?.Invoke(eventArgs); } /// public void OnNodeCreated(NodeCreateEventArgs eventArgs) { NodeCreated?.Invoke(eventArgs); } /// public void OnNodeRemoved(NodeRemoveEventArgs eventArgs) { NodeRemoved?.Invoke(eventArgs); } /// public void OnNodePlace(NodePlaceEventArgs eventArgs) { NodePlace?.Invoke(eventArgs); } /// public void OnNodeTakeOut(NodeTakeOutEventArgs eventArgs) { NodeTakeOut?.Invoke(eventArgs); } /// public void OnStartNodeChanged(StartNodeChangeEventArgs eventArgs) { StartNodeChanged?.Invoke(eventArgs); } /// public void OnFlowRunComplete(FlowEventArgs eventArgs) { FlowRunComplete?.Invoke(eventArgs); } /// public void OnMonitorObjectChanged(MonitorObjectEventArgs eventArgs) { MonitorObjectChanged?.Invoke(eventArgs); } /// public void OnNodeInterruptStateChanged(NodeInterruptStateChangeEventArgs eventArgs) { NodeInterruptStateChanged?.Invoke(eventArgs); } /// public void OnInterruptTriggered(InterruptTriggerEventArgs eventArgs) { InterruptTriggered?.Invoke(eventArgs); } /// public void OnIOCMembersChanged(IOCMembersChangedEventArgs eventArgs) { IOCMembersChanged?.Invoke(eventArgs); } /// public void OnNodeLocated(NodeLocatedEventArgs eventArgs) { NodeLocated?.Invoke(eventArgs); } /// public void OnEnvOutput(InfoType type, string value) { EnvOutput?.Invoke(type, value); } } /// /// 轻量级流程环境实现 /// public class LightweightFlowEnvironment : IFlowEnvironment { /// /// 轻量级流程环境构造函数,接受一个流程环境事件接口。 /// /// public LightweightFlowEnvironment(IFlowEnvironmentEvent lightweightFlowEnvironmentEvent) { this.Event = lightweightFlowEnvironmentEvent; } /// public void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Debug) { Console.WriteLine(message); } /// public ISereinIOC IOC => throw new NotImplementedException(); /// public IFlowEdit FlowEdit => throw new NotImplementedException(); /// public IFlowControl FlowControl => throw new NotImplementedException(); /// public IFlowEnvironmentEvent Event { get; private set; } /// public string EnvName => throw new NotImplementedException(); /// public string ProjectFileLocation => throw new NotImplementedException(); /// public bool _IsGlobalInterrupt => throw new NotImplementedException(); /// public bool IsControlRemoteEnv => throw new NotImplementedException(); /// public InfoClass InfoClass { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } /// public RunState FlowState { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } /// public IFlowEnvironment CurrentEnv => throw new NotImplementedException(); /// public UIContextOperation UIContextOperation => throw new NotImplementedException(); /* public Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token) { throw new NotImplementedException(); }*/ /// public void ExitRemoteEnv() { throw new NotImplementedException(); } /// public Task GetEnvInfoAsync() { throw new NotImplementedException(); } /// public SereinProjectData GetProjectInfoAsync() { throw new NotImplementedException(); } /// public void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true) { throw new NotImplementedException(); } /// public void LoadLibrary(string dllPath) { throw new NotImplementedException(); } /// public bool LoadNativeLibraryOfRuning(string file) { throw new NotImplementedException(); } /// public void LoadProject(string filePath) { throw new NotImplementedException(); } /// public Task LoadProjetAsync(string filePath) { throw new NotImplementedException(); } /// public Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value) { throw new NotImplementedException(); } /// public void SaveProject() { throw new NotImplementedException(); } /// public void SetUIContextOperation(UIContextOperation uiContextOperation) { throw new NotImplementedException(); } /// public Task StartRemoteServerAsync(int port = 7525) { throw new NotImplementedException(); } /// public void StopRemoteServer() { throw new NotImplementedException(); } /// public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del) { throw new NotImplementedException(); } /// public bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo mdInfo) { throw new NotImplementedException(); } /// public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel) { throw new NotImplementedException(); } /// public bool TryUnloadLibrary(string assemblyFullName) { throw new NotImplementedException(); } } }