diff --git a/Library/Api/ISereinIoc.cs b/Library/Api/ISereinIoc.cs index 2d64cb5..7e7b914 100644 --- a/Library/Api/ISereinIoc.cs +++ b/Library/Api/ISereinIoc.cs @@ -11,11 +11,31 @@ namespace Serein.Library.Api /// object GetOrCreateServiceInstance(Type serviceType, params object[] parameters); T CreateServiceInstance(params object[] parameters); - ISereinIoc Reset(); // 清空 + /// + /// 清空 + /// + /// + ISereinIoc Reset(); + + /// + /// 以已存在的实例对象注册 + /// + /// + /// + ISereinIoc RegisterInstantiate(object instantiate); + /// + /// 注册实例 + /// ISereinIoc Register(Type type, params object[] parameters); ISereinIoc Register(params object[] parameters); ISereinIoc Register(params object[] parameters) where TImplementation : TService; + /// + /// 获取或创建并注入目标类型 + /// T GetOrInstantiate(); + /// + /// 获取或创建并注入目标类型 + /// object GetOrInstantiate(Type type); /// diff --git a/Library/Entity/MethodDetails.cs b/Library/Entity/MethodDetails.cs index f534ab0..270db53 100644 --- a/Library/Entity/MethodDetails.cs +++ b/Library/Entity/MethodDetails.cs @@ -33,7 +33,7 @@ namespace Serein.Library.Entity } /// - /// 作用实例 + /// 作用实例的类型 /// public Type ActingInstanceType { get; set; } diff --git a/Library/Enums/NodeType.cs b/Library/Enums/NodeType.cs index a3f1719..2b23cb6 100644 --- a/Library/Enums/NodeType.cs +++ b/Library/Enums/NodeType.cs @@ -35,7 +35,9 @@ namespace Serein.Library.Enums Action, } - + /// + /// 生成的节点控件 + /// public enum NodeControlType { None, diff --git a/Library/Utils/SereinIoc.cs b/Library/Utils/SereinIoc.cs index f2d8417..d05bea0 100644 --- a/Library/Utils/SereinIoc.cs +++ b/Library/Utils/SereinIoc.cs @@ -70,6 +70,21 @@ namespace Serein.Library.Utils return this; } + public ISereinIoc RegisterInstantiate(object instantiate) + { + //var type = instantiate.GetType(); + if (!_typeMappings.TryGetValue(instantiate.GetType().FullName,out var type)) + { + _typeMappings[type.FullName] = type; + } + + if(!_dependencies.TryGetValue(type.FullName, out var instancei)) + { + _dependencies[type.FullName] = Activator.CreateInstance(type); + } + // _dependencies.AddOrUpdate(type.FullName,s => instantiate, (s,o) => instantiate); + return this; + } public ISereinIoc Register(Type type, params object[] parameters) { @@ -127,21 +142,20 @@ namespace Serein.Library.Utils } public ISereinIoc Build() { + + // 遍历已注册类型 foreach (var type in _typeMappings.Values) { - + // 如果没有创建实例,则创建对应的实例 if(!_dependencies.ContainsKey(type.FullName)) { - _dependencies[type.FullName] = Activator.CreateInstance(type); - } - } + // 注入实例的依赖项 foreach (var instance in _dependencies.Values) { - InjectDependencies(instance); // 替换占位符 } @@ -155,7 +169,7 @@ namespace Serein.Library.Utils { var instance = Activator.CreateInstance(controllerType, parameters); if(instance != null) - { + { InjectDependencies(instance); } return instance; @@ -285,6 +299,7 @@ namespace Serein.Library.Utils return this; } + #endregion } diff --git a/NodeFlow/Base/NodeModelBaseFunc.cs b/NodeFlow/Base/NodeModelBaseFunc.cs index 6fe0e04..0a3bb54 100644 --- a/NodeFlow/Base/NodeModelBaseFunc.cs +++ b/NodeFlow/Base/NodeModelBaseFunc.cs @@ -44,6 +44,73 @@ namespace Serein.NodeFlow.Base }; } + + + + /// + /// 开始执行 + /// + /// + /// + public async Task StartExecution(IDynamicContext context) + { + var cts = context.SereinIoc.GetOrInstantiate(); + + Stack stack = []; + stack.Push(this); + + while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环 + { + // 从栈中弹出一个节点作为当前节点进行处理 + var currentNode = stack.Pop(); + + // 设置方法执行的对象 + if (currentNode.MethodDetails is not null) + { + // currentNode.MethodDetails.ActingInstance ??= context.SereinIoc.GetOrInstantiate(MethodDetails.ActingInstanceType); + // currentNode.MethodDetails.ActingInstance = context.SereinIoc.GetOrInstantiate(MethodDetails.ActingInstanceType); + + currentNode.MethodDetails.ActingInstance = context.SereinIoc.GetOrInstantiate(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 (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == NodeType.Flipflop) + { + // 触发器节点 + currentNode.FlowData = await currentNode.ExecuteAsync(context); + } + else + { + // 动作节点 + currentNode.FlowData = currentNode.Execute(context); + } + + ConnectionType connection = currentNode.FlowState switch + { + FlowStateType.Succeed => ConnectionType.IsSucceed, + FlowStateType.Fail => ConnectionType.IsFail, + FlowStateType.Error => ConnectionType.IsError, + _ => throw new Exception("非预期的枚举值") + }; + var nextNodes = currentNode.SuccessorNodes[connection]; + + // 将下一个节点集合中的所有节点逆序推入栈中 + for (int i = nextNodes.Count - 1; i >= 0; i--) + { + nextNodes[i].PreviousNode = currentNode; + stack.Push(nextNodes[i]); + } + } + } + + /// /// 执行节点对应的方法 /// @@ -76,10 +143,12 @@ namespace Serein.NodeFlow.Base } else { - result = ((Func)del).Invoke(md.ActingInstance, parameters); + var func = del as Func; + //result = ((Func)del).Invoke(md.ActingInstance, parameters); + result = func?.Invoke(md.ActingInstance, parameters); } } - + FlowState = FlowStateType.Succeed; return result; } catch (Exception ex) @@ -138,66 +207,6 @@ namespace Serein.NodeFlow.Base return result; } - /// - /// 开始执行 - /// - /// - /// - public async Task StartExecution(IDynamicContext context) - { - var cts = context.SereinIoc.GetOrInstantiate(); - - Stack stack = []; - stack.Push(this); - - while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环 - { - // 从栈中弹出一个节点作为当前节点进行处理 - var currentNode = stack.Pop(); - - // 设置方法执行的对象 - if (currentNode.MethodDetails != null) - { - currentNode.MethodDetails.ActingInstance ??= context.SereinIoc.GetOrInstantiate(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 (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == NodeType.Flipflop) - { - // 触发器节点 - currentNode.FlowData = await currentNode.ExecuteAsync(context); - } - else - { - // 动作节点 - currentNode.FlowData = currentNode.Execute(context); - } - - ConnectionType connection = currentNode.FlowState switch - { - FlowStateType.Succeed => ConnectionType.IsSucceed, - FlowStateType.Fail => ConnectionType.IsFail, - FlowStateType.Error => ConnectionType.IsError, - _ => throw new Exception("非预期的枚举值") - }; - var nextNodes = currentNode.SuccessorNodes[connection]; - - // 将下一个节点集合中的所有节点逆序推入栈中 - for (int i = nextNodes.Count - 1; i >= 0; i--) - { - nextNodes[i].PreviousNode = currentNode; - stack.Push(nextNodes[i]); - } - } - } - /// /// 获取对应的参数数组 /// diff --git a/NodeFlow/FlowEnvironment.cs b/NodeFlow/FlowEnvironment.cs index 555ec60..c831cce 100644 --- a/NodeFlow/FlowEnvironment.cs +++ b/NodeFlow/FlowEnvironment.cs @@ -100,6 +100,9 @@ namespace Serein.NodeFlow private NodeModelBase? _startNode = null; + /// + /// 起始节点 + /// public NodeModelBase StartNode { get { @@ -119,17 +122,20 @@ namespace Serein.NodeFlow } } } + /// + /// 异步运行 + /// + /// public async Task StartAsync() { - nodeFlowStarter = new FlowStarter(SereinIoc, MethodDetailss); + nodeFlowStarter = new FlowStarter(SereinIoc); var nodes = Nodes.Values.ToList(); var flipflopNodes = nodes.Where(it => it.MethodDetails?.MethodDynamicType == NodeType.Flipflop - && it.PreviousNodes.Count == 0 - && it.IsStart != true) + && it.IsStart == false) .Select(it => it as SingleFlipflopNode) .ToList(); - await nodeFlowStarter.RunAsync(StartNode, this, flipflopNodes); - OnFlowRunComplete?.Invoke(new FlowEventArgs()); + + await nodeFlowStarter.RunAsync(StartNode, this, MethodDetailss, flipflopNodes); } public void Exit() { @@ -150,7 +156,7 @@ namespace Serein.NodeFlow } - #region 数据交互 + #region 对外暴露的接口 /// /// 获取方法描述 @@ -328,8 +334,10 @@ namespace Serein.NodeFlow (var assembly, var list) = LoadAssembly(dllPath); if (assembly is not null && list.Count > 0) { + MethodDetailss.AddRange(list); OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list)); } + } /// @@ -480,11 +488,17 @@ namespace Serein.NodeFlow // 遍历扫描的类型 foreach (var item in scanTypes) { - //加载DLL,创建 MethodDetails、实例作用对象、委托方法 + // 加载DLL,创建 MethodDetails、实例作用对象、委托方法 var itemMethodDetails = MethodDetailsHelperTmp.GetList(item, false); + foreach(var md in itemMethodDetails) + { + // var instanceType = + // Activator.CreateInstance(md.ActingInstanceType); + // SereinIoc.RegisterInstantiate(md.ActingInstance); + SereinIoc.Register(md.ActingInstanceType); + } methodDetails.AddRange(itemMethodDetails); } - LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中 LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径 return (assembly, methodDetails); @@ -571,8 +585,6 @@ namespace Serein.NodeFlow } #endregion - - #region 视觉元素交互 #region 本地交互(WPF) diff --git a/NodeFlow/FlowStarter.cs b/NodeFlow/FlowStarter.cs index 5a62511..64a6805 100644 --- a/NodeFlow/FlowStarter.cs +++ b/NodeFlow/FlowStarter.cs @@ -14,14 +14,19 @@ namespace Serein.NodeFlow /// /// /// - public class FlowStarter(ISereinIoc serviceContainer, List methodDetails) - + public class FlowStarter { - private readonly ISereinIoc ServiceContainer = serviceContainer; - private readonly List methodDetails = methodDetails; - private Action ExitAction = null; //退出方法 - private IDynamicContext context = null; //上下文 - public NodeRunCts MainCts; + public FlowStarter(ISereinIoc serviceContainer/*, List methodDetails*/) + { + SereinIoc = serviceContainer; + + } + + private ISereinIoc SereinIoc { get; } + // private List MethodDetailss { get; } + private Action ExitAction { get; set; } = null; //退出方法 + private IDynamicContext Context { get; set; } = null; //上下文 + public NodeRunCts MainCts { get; set; } /// /// 开始运行 @@ -29,7 +34,7 @@ namespace Serein.NodeFlow /// /// // public async Task RunAsync(List nodes, IFlowEnvironment flowEnvironment) - public async Task RunAsync(NodeModelBase startNode, IFlowEnvironment flowEnvironment, List flipflopNodes) + public async Task RunAsync(NodeModelBase startNode, IFlowEnvironment flowEnvironment, List methodDetailss, List flipflopNodes) { // var startNode = nodes.FirstOrDefault(p => p.IsStart); if (startNode == null) { return; } @@ -38,18 +43,32 @@ namespace Serein.NodeFlow if (isNetFramework) { - context = new Serein.Library.Framework.NodeFlow.DynamicContext(ServiceContainer, flowEnvironment); + Context = new Serein.Library.Framework.NodeFlow.DynamicContext(SereinIoc, flowEnvironment); } else { - context = new Serein.Library.Core.NodeFlow.DynamicContext(ServiceContainer, flowEnvironment); + Context = new Serein.Library.Core.NodeFlow.DynamicContext(SereinIoc, flowEnvironment); } - MainCts = ServiceContainer.CreateServiceInstance(); + MainCts = SereinIoc.CreateServiceInstance(); + + foreach (var md in methodDetailss) + { + SereinIoc.Register(md.ActingInstanceType); + } + SereinIoc.Build(); + foreach (var md in flipflopNodes.Select(it => it.MethodDetails).ToArray()) + { + md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType); + } + foreach (var md in methodDetailss) + { + md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType); + } - var initMethods = methodDetails.Where(it => it.MethodDynamicType == NodeType.Init).ToList(); - var loadingMethods = methodDetails.Where(it => it.MethodDynamicType == NodeType.Loading).ToList(); - var exitMethods = methodDetails.Where(it => it.MethodDynamicType == NodeType.Exit).ToList(); + var initMethods = methodDetailss.Where(it => it.MethodDynamicType == NodeType.Init).ToList(); + var loadingMethods = methodDetailss.Where(it => it.MethodDynamicType == NodeType.Loading).ToList(); + var exitMethods = methodDetailss.Where(it => it.MethodDynamicType == NodeType.Exit).ToList(); ExitAction = () => { //ServiceContainer.Run((web) => @@ -58,29 +77,31 @@ namespace Serein.NodeFlow //}); foreach (MethodDetails? md in exitMethods) { - object?[]? args = [context]; + md.ActingInstance = Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType); + object?[]? args = [Context]; object?[]? data = [md.ActingInstance, args]; md.MethodDelegate.DynamicInvoke(data); } - if (context != null && context.NodeRunCts != null && !context.NodeRunCts.IsCancellationRequested) + if (Context != null && Context.NodeRunCts != null && !Context.NodeRunCts.IsCancellationRequested) { - context.NodeRunCts.Cancel(); + Context.NodeRunCts.Cancel(); } if (MainCts != null && !MainCts.IsCancellationRequested) MainCts.Cancel(); - ServiceContainer.Reset(); + SereinIoc.Reset(); }; - + Context.SereinIoc.Build(); foreach (var md in initMethods) // 初始化 - 调用方法 { - object?[]? args = [context]; + md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType); + object?[]? args = [Context]; object?[]? data = [md.ActingInstance, args]; md.MethodDelegate.DynamicInvoke(data); } - context.SereinIoc.Build(); - + Context.SereinIoc.Build(); foreach (var md in loadingMethods) // 加载 { - object?[]? args = [context]; + md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType); + object?[]? args = [Context]; object?[]? data = [md.ActingInstance, args]; md.MethodDelegate.DynamicInvoke(data); } @@ -93,19 +114,25 @@ namespace Serein.NodeFlow { await FlipflopExecute(node, flowEnvironment); }).ToArray(); - + _ = Task.WhenAll(tasks); try { await Task.Run(async () => { - await Task.WhenAll([startNode.StartExecution(context), .. tasks]); + await startNode.StartExecution(Context); + //await Task.WhenAll([startNode.StartExecution(Context), .. tasks]); }); + // 等待结束 + while (!MainCts.IsCancellationRequested) + { + await Task.Delay(100); + } } catch (Exception ex) { await Console.Out.WriteLineAsync(ex.ToString()); } - + } /// @@ -113,7 +140,7 @@ namespace Serein.NodeFlow /// private async Task FlipflopExecute(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment flowEnvironment) { - DynamicContext context = new DynamicContext(ServiceContainer, flowEnvironment); + DynamicContext context = new DynamicContext(SereinIoc, flowEnvironment); MethodDetails md = singleFlipFlopNode.MethodDetails; var del = md.MethodDelegate; try @@ -128,15 +155,17 @@ namespace Serein.NodeFlow object?[]? parameters = singleFlipFlopNode.GetParameters(context, md); // 调用委托并获取结果 + md.ActingInstance = context.SereinIoc.GetOrInstantiate(md.ActingInstanceType); + IFlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters); if (flipflopContext.State == FlowStateType.Succeed) { singleFlipFlopNode.FlowState = FlowStateType.Succeed; singleFlipFlopNode.FlowData = flipflopContext.Data; - var tasks = singleFlipFlopNode.PreviousNodes[ConnectionType.IsSucceed].Select(nextNode => + var tasks = singleFlipFlopNode.SuccessorNodes[ConnectionType.IsSucceed].Select(nextNode => { - var context = new DynamicContext(ServiceContainer,flowEnvironment); + var context = new DynamicContext(SereinIoc,flowEnvironment); nextNode.PreviousNode = singleFlipFlopNode; return nextNode.StartExecution(context); }).ToArray(); diff --git a/NodeFlow/Tool/MethodDetailsHelper.cs b/NodeFlow/Tool/MethodDetailsHelper.cs index d22e8b7..5f59431 100644 --- a/NodeFlow/Tool/MethodDetailsHelper.cs +++ b/NodeFlow/Tool/MethodDetailsHelper.cs @@ -76,13 +76,13 @@ public static class MethodDetailsHelperTmp var dllTypeName = $"{assemblyName}.{type.Name}"; - object instance = Activator.CreateInstance(type); + // object instance = Activator.CreateInstance(type); var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}"; return new MethodDetails { ActingInstanceType = type, - ActingInstance = instance, + // ActingInstance = instance, MethodName = dllTypeMethodName, MethodDelegate = methodDelegate, MethodDynamicType = attribute.MethodDynamicType,