diff --git a/Library.Core/NodeFlow/DynamicContext.cs b/Library.Core/NodeFlow/DynamicContext.cs
index b29e27c..0a62ad4 100644
--- a/Library.Core/NodeFlow/DynamicContext.cs
+++ b/Library.Core/NodeFlow/DynamicContext.cs
@@ -9,7 +9,7 @@ namespace Serein.Library.Core.NodeFlow
///
public class DynamicContext: IDynamicContext
{
- public DynamicContext(ISereinIoc sereinIoc, IFlowEnvironment flowEnvironment)
+ public DynamicContext(ISereinIOC sereinIoc, IFlowEnvironment flowEnvironment)
{
SereinIoc = sereinIoc;
FlowEnvironment = flowEnvironment;
@@ -17,7 +17,7 @@ namespace Serein.Library.Core.NodeFlow
}
public NodeRunCts NodeRunCts { get; set; }
- public ISereinIoc SereinIoc { get; }
+ public ISereinIOC SereinIoc { get; }
public IFlowEnvironment FlowEnvironment { get; }
public Task CreateTimingTask(Action action, int time = 100, int count = -1)
diff --git a/Library.Framework/NodeFlow/DynamicContext.cs b/Library.Framework/NodeFlow/DynamicContext.cs
index 6107d70..4ae4329 100644
--- a/Library.Framework/NodeFlow/DynamicContext.cs
+++ b/Library.Framework/NodeFlow/DynamicContext.cs
@@ -12,13 +12,13 @@ namespace Serein.Library.Framework.NodeFlow
///
public class DynamicContext : IDynamicContext
{
- public DynamicContext(ISereinIoc sereinIoc, IFlowEnvironment flowEnvironment)
+ public DynamicContext(ISereinIOC sereinIoc, IFlowEnvironment flowEnvironment)
{
SereinIoc = sereinIoc;
FlowEnvironment = flowEnvironment;
}
public NodeRunCts NodeRunCts { get; set; }
- public ISereinIoc SereinIoc { get; }
+ public ISereinIOC SereinIoc { get; }
public IFlowEnvironment FlowEnvironment { get; }
public Task CreateTimingTask(Action action, int time = 100, int count = -1)
{
diff --git a/Library/Api/IDynamicContext.cs b/Library/Api/IDynamicContext.cs
index 266319e..d6bcc4a 100644
--- a/Library/Api/IDynamicContext.cs
+++ b/Library/Api/IDynamicContext.cs
@@ -7,7 +7,7 @@ namespace Serein.Library.Api
public interface IDynamicContext
{
IFlowEnvironment FlowEnvironment { get; }
- ISereinIoc SereinIoc { get; }
+ ISereinIOC SereinIoc { get; }
NodeRunCts NodeRunCts { get; set; }
Task CreateTimingTask(Action action, int time = 100, int count = -1);
}
diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs
index 19ceb72..b0b603c 100644
--- a/Library/Api/IFlowEnvironment.cs
+++ b/Library/Api/IFlowEnvironment.cs
@@ -7,48 +7,22 @@ using System.Threading.Tasks;
namespace Serein.Library.Api
{
-
- public class FlowEventArgs : EventArgs
- {
- public bool IsSucceed { get; protected set; } = true;
- public string ErrorTips { get; protected set; } = string.Empty;
- }
-
-
+ #region 环境委托
+ ///
+ /// 流程运行完成
+ ///
+ ///
public delegate void FlowRunCompleteHandler(FlowEventArgs eventArgs);
-
///
- /// 加载节点
+ /// 加载项目文件时成功加载了节点
///
public delegate void LoadNodeHandler(LoadNodeEventArgs eventArgs);
- public class LoadNodeEventArgs : FlowEventArgs
- {
- public LoadNodeEventArgs(NodeInfo NodeInfo, MethodDetails MethodDetailss)
- {
- this.NodeInfo = NodeInfo;
- this.MethodDetailss = MethodDetailss;
- }
- public NodeInfo NodeInfo { get; protected set; }
- public MethodDetails MethodDetailss { get; protected set; }
- }
-
///
- /// 加载DLL
+ /// 加载项目文件时成功加载了DLL文件
///
- ///
public delegate void LoadDLLHandler(LoadDLLEventArgs eventArgs);
- public class LoadDLLEventArgs : FlowEventArgs
- {
- public LoadDLLEventArgs(Assembly Assembly, List MethodDetailss)
- {
- this.Assembly = Assembly;
- this.MethodDetailss = MethodDetailss;
- }
- public Assembly Assembly { get; protected set; }
- public List MethodDetailss { get; protected set; }
- }
///
/// 运行环境节点连接发生了改变
@@ -57,43 +31,132 @@ namespace Serein.Library.Api
///
///
public delegate void NodeConnectChangeHandler(NodeConnectChangeEventArgs eventArgs);
+
+ ///
+ /// 环境中加载了一个节点
+ ///
+ ///
+ ///
+ ///
+ public delegate void NodeCreateHandler(NodeCreateEventArgs eventArgs);
+
+ ///
+ /// 环境中流程起始节点发生了改变
+ ///
+ ///
+ public delegate void StartNodeChangeHandler(StartNodeChangeEventArgs eventArgs);
+ #endregion
+
+ #region 环境事件签名
+
+ ///
+ /// 流程事件签名基类
+ ///
+ public class FlowEventArgs : EventArgs
+ {
+ ///
+ /// 是否完成
+ ///
+ public bool IsSucceed { get; protected set; } = true;
+ ///
+ /// 错误提示
+ ///
+ public string ErrorTips { get; protected set; } = string.Empty;
+ }
+ public class LoadNodeEventArgs : FlowEventArgs
+ {
+ public LoadNodeEventArgs(NodeInfo NodeInfo, MethodDetails MethodDetailss)
+ {
+ this.NodeInfo = NodeInfo;
+ this.MethodDetailss = MethodDetailss;
+ }
+ ///
+ /// 项目文件节点信息参数
+ ///
+ public NodeInfo NodeInfo { get; protected set; }
+ ///
+ /// 已加载在环境中的方法描述
+ ///
+ public MethodDetails MethodDetailss { get; protected set; }
+ }
+
+
+ public class LoadDLLEventArgs : FlowEventArgs
+ {
+ public LoadDLLEventArgs(Assembly Assembly, List MethodDetailss)
+ {
+ this.Assembly = Assembly;
+ this.MethodDetailss = MethodDetailss;
+ }
+ ///
+ /// 已加载了的程序集
+ ///
+ public Assembly Assembly { get; protected set; }
+ ///
+ /// dll文件中有效的流程方法描述
+ ///
+ public List MethodDetailss { get; protected set; }
+ }
+
+
public class NodeConnectChangeEventArgs : FlowEventArgs
{
- public enum ChangeTypeEnum
+ ///
+ /// 连接关系改变类型
+ ///
+ public enum ConnectChangeType
{
+ ///
+ /// 创建
+ ///
Create,
+ ///
+ /// 移除
+ ///
Remote,
}
- public NodeConnectChangeEventArgs(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType, ChangeTypeEnum changeType)
+ public NodeConnectChangeEventArgs(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType, ConnectChangeType changeType)
{
this.FromNodeGuid = fromNodeGuid;
this.ToNodeGuid = toNodeGuid;
this.ConnectionType = connectionType;
this.ChangeType = changeType;
}
+ ///
+ /// 连接关系中始节点的Guid
+ ///
public string FromNodeGuid { get; protected set; }
+ ///
+ /// 连接关系中目标节点的Guid
+ ///
public string ToNodeGuid { get; protected set; }
+ ///
+ /// 连接类型
+ ///
public ConnectionType ConnectionType { get; protected set; }
- public ChangeTypeEnum ChangeType { get; protected set; }
+ ///
+ /// 表示此次需要在两个节点之间创建连接关系,或是移除连接关系
+ ///
+ public ConnectChangeType ChangeType { get; protected set; }
}
- ///
- /// 添加了节点
- ///
- ///
- ///
- ///
- public delegate void NodeCreateHandler(NodeCreateEventArgs eventArgs);
+
public class NodeCreateEventArgs : FlowEventArgs
{
public NodeCreateEventArgs(object nodeModel)
{
this.NodeModel = nodeModel;
}
+ ///
+ /// 节点Model对象,目前需要手动转换对应的类型
+ ///
public object NodeModel { get; private set; }
}
-
+ ///
+ /// 环境中移除了一个节点
+ ///
+ ///
public delegate void NodeRemoteHandler(NodeRemoteEventArgs eventArgs);
public class NodeRemoteEventArgs : FlowEventArgs
@@ -102,24 +165,32 @@ namespace Serein.Library.Api
{
this.NodeGuid = nodeGuid;
}
+ ///
+ /// 被移除节点的Guid
+ ///
public string NodeGuid { get; private set; }
}
- public delegate void StartNodeChangeHandler(StartNodeChangeEventArgs eventArgs);
- public class StartNodeChangeEventArgs: FlowEventArgs
+ public class StartNodeChangeEventArgs : FlowEventArgs
{
public StartNodeChangeEventArgs(string oldNodeGuid, string newNodeGuid)
{
this.OldNodeGuid = oldNodeGuid;
this.NewNodeGuid = newNodeGuid; ;
}
- public string OldNodeGuid { get; private set; }
- public string NewNodeGuid { get; private set; }
- }
-
+ ///
+ /// 原来的起始节点Guid
+ ///
+ public string OldNodeGuid { get; private set; }
+ ///
+ /// 新的起始节点Guid
+ ///
+ public string NewNodeGuid { get; private set; }
+ }
+ #endregion
public interface IFlowEnvironment
{
diff --git a/Library/Api/ISereinIoc.cs b/Library/Api/ISereinIoc.cs
index d4aee92..06ef569 100644
--- a/Library/Api/ISereinIoc.cs
+++ b/Library/Api/ISereinIoc.cs
@@ -4,24 +4,19 @@ using System.Text;
namespace Serein.Library.Api
{
- public interface ISereinIoc
+ public interface ISereinIOC
{
- ///
- /// 获取或创建类型的实例(不注入依赖项)
- ///
- object GetOrCreateServiceInstance(Type serviceType, params object[] parameters);
- T GetOrCreateServiceInstance(params object[] parameters);
///
/// 清空
///
///
- ISereinIoc Reset();
+ ISereinIOC Reset();
///
/// 注册实例
///
- ISereinIoc Register(Type type, params object[] parameters);
- ISereinIoc Register(params object[] parameters);
- ISereinIoc Register(params object[] parameters) where TImplementation : TService;
+ ISereinIOC Register(Type type, params object[] parameters);
+ ISereinIOC Register(params object[] parameters);
+ ISereinIOC Register(params object[] parameters) where TImplementation : TService;
///
/// 获取或创建并注入目标类型
///
@@ -35,15 +30,15 @@ namespace Serein.Library.Api
/// 创建目标类型的对象, 并注入依赖项
///
object Instantiate(Type type, params object[] parameters);
- ISereinIoc Build();
- ISereinIoc Run(Action action);
- ISereinIoc Run(Action action);
- ISereinIoc Run(Action action);
- ISereinIoc Run(Action action);
- ISereinIoc Run(Action action);
- ISereinIoc Run(Action action);
- ISereinIoc Run(Action action);
- ISereinIoc Run(Action action);
+ ISereinIOC Build();
+ ISereinIOC Run(Action action);
+ ISereinIOC Run(Action action);
+ ISereinIOC Run(Action action);
+ ISereinIOC Run(Action action);
+ ISereinIOC Run(Action action);
+ ISereinIOC Run(Action action);
+ ISereinIOC Run(Action action);
+ ISereinIOC Run(Action action);
}
}
diff --git a/Library/Utils/SereinIoc.cs b/Library/Utils/SereinIoc.cs
index 2093198..87c1163 100644
--- a/Library/Utils/SereinIoc.cs
+++ b/Library/Utils/SereinIoc.cs
@@ -11,7 +11,7 @@ namespace Serein.Library.Utils
///
/// IOC管理容器
///
- public class SereinIoc : ISereinIoc
+ public class SereinIOC : ISereinIOC
{
///
/// 实例集合
@@ -33,78 +33,31 @@ namespace Serein.Library.Utils
///
private readonly List _waitingForInstantiation;
- public SereinIoc()
+ public SereinIOC()
{
// 首先注册自己
_dependencies = new ConcurrentDictionary
{
- [typeof(ISereinIoc).FullName] = this
+ [typeof(ISereinIOC).FullName] = this
};
_typeMappings = new ConcurrentDictionary
{
- [typeof(ISereinIoc).FullName] = typeof(ISereinIoc)
+ [typeof(ISereinIOC).FullName] = typeof(ISereinIOC)
};
_unfinishedDependencies = new ConcurrentDictionary>();
_waitingForInstantiation = new List();
}
- ///
- /// 获取或创建实例对象(不注入对象的依赖项)
- ///
- /// 目标类型
- /// 构造函数的参数
- ///
- public object GetOrCreateServiceInstance(Type type, params object[] parameters)
- {
- if (_dependencies.ContainsKey(type.FullName))
- {
- return _dependencies[type.FullName];
- }
- else
- {
- var instance = Activator.CreateInstance(type); // 创建目标类型的实例对象
- InjectDependencies(instance);// 注入目标对象的依赖项
- _dependencies[type.FullName] = instance; // 记录实例
- return instance;
- }
- }
- ///
- /// 泛型方法, 获取或创建实例对象(不注入对象的依赖项)
- ///
- /// 目标类型
- /// 构造函数的参数
- ///
- public T GetOrCreateServiceInstance(params object[] parameters)
- {
- return (T)GetOrCreateServiceInstance(typeof(T), parameters);
- }
- ///
- /// 清空容器对象
- ///
- ///
- public ISereinIoc Reset()
- {
- // 检查是否存在非托管资源
- foreach(var instancei in _dependencies.Values)
- {
- if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable)
- {
- disposable.Dispose();
- }
- }
- _typeMappings.Clear();
- _dependencies.Clear();
- _waitingForInstantiation.Clear();
- return this;
- }
+
+ #region 类型的注册
///
/// 注册类型
///
/// 目标类型
/// 参数
- public ISereinIoc Register(Type type, params object[] parameters)
+ public ISereinIOC Register(Type type, params object[] parameters)
{
RegisterType(type.FullName, type);
return this;
@@ -114,7 +67,7 @@ namespace Serein.Library.Utils
///
/// 目标类型
/// 参数
- public ISereinIoc Register(params object[] parameters)
+ public ISereinIOC Register(params object[] parameters)
{
var type = typeof(T);
RegisterType(type.FullName, type);
@@ -122,61 +75,90 @@ namespace Serein.Library.Utils
}
- public ISereinIoc Register(params object[] parameters)
+ public ISereinIOC Register(params object[] parameters)
where TImplementation : TService
{
var typeFullName = typeof(TService).FullName;
RegisterType(typeFullName, typeof(TImplementation));
return this;
- }
-
+ }
+ #endregion
///
- /// 注册
+ /// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。
///
- ///
- ///
public object GetOrInstantiate(Type type)
{
+ // 尝试从容器中获取对象
if (!_dependencies.TryGetValue(type.FullName, out object value))
{
- Register(type);
-
- value = Instantiate(type);
-
- InjectDependencies(type);
+ Register(type);// 注册类型信息
+ value = Instantiate(type); // 创建实例对象,并注入依赖
+ _dependencies.TryAdd(type.FullName, value); // 登记到IOC容器中
}
-
-
-
- return value;
-
+ return value;
}
+ ///
+ /// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。
+ ///
public T GetOrInstantiate()
{
- if(!_dependencies.TryGetValue(typeof(T).FullName, out object value))
- {
- Register(typeof(T));
- value = Instantiate(typeof(T));
- }
-
+ var value = Instantiate(typeof(T));
return (T)value;
- //throw new InvalidOperationException("目标类型未创建实例");
+ }
+
+ ///
+ /// 根据类型生成对应的实例,并注入其中的依赖项(类型信息不登记到IOC容器中)
+ ///
+ ///
+ ///
+ ///
+ public object Instantiate(Type controllerType, params object[] parameters)
+ {
+ var instance = CreateInstance(controllerType, parameters); // 创建目标类型的实例
+ if(instance != null)
+ {
+ InjectDependencies(instance); // 完成创建后注入实例需要的依赖项
+ }
+ return instance;
+ }
+
+ #region 容器管理(清空,绑定)
+
+ ///
+ /// 清空容器对象
+ ///
+ ///
+ public ISereinIOC Reset()
+ {
+ // 检查是否存在非托管资源
+ foreach (var instancei in _dependencies.Values)
+ {
+ if (typeof(IDisposable).IsAssignableFrom(instancei.GetType()) && instancei is IDisposable disposable)
+ {
+ disposable?.Dispose();
+ }
+ }
+ _unfinishedDependencies?.Clear();
+ _typeMappings?.Clear();
+ _dependencies?.Clear();
+ _waitingForInstantiation?.Clear();
+ return this;
}
///
/// 实例化所有已注册的类型,并尝试绑定
///
///
- public ISereinIoc Build()
+ public ISereinIOC Build()
{
// 遍历已注册类型
foreach (var type in _typeMappings.Values.ToArray())
{
-
- if(_dependencies.ContainsKey(type.FullName))
+
+ if (_dependencies.ContainsKey(type.FullName))
{
// 已经存在实例,不用管
}
@@ -186,7 +168,7 @@ namespace Serein.Library.Utils
_dependencies[type.FullName] = CreateInstance(type);
}
// 移除类型的注册记录
- _typeMappings.TryRemove(type.FullName,out _);
+ _typeMappings.TryRemove(type.FullName, out _);
}
// 注入实例的依赖项
@@ -198,20 +180,12 @@ namespace Serein.Library.Utils
//var instance = Instantiate(item.Value);
// TryInstantiateWaitingDependencies();
-
+
return this;
- }
-
- public object Instantiate(Type controllerType, params object[] parameters)
- {
- var instance = CreateInstance(controllerType, parameters);
- if(instance != null)
- {
- InjectDependencies(instance);
- }
- return instance;
- }
+ }
+ #endregion
+ #region 私有方法
///
@@ -233,14 +207,14 @@ namespace Serein.Library.Utils
private object CreateInstance(Type type, params object[] parameters)
{
var instance = Activator.CreateInstance(type);
- if(_unfinishedDependencies.TryGetValue(type.FullName, out var unfinishedPropertyList))
+ if (_unfinishedDependencies.TryGetValue(type.FullName, out var unfinishedPropertyList))
{
foreach ((object obj, PropertyInfo property) in unfinishedPropertyList)
{
property.SetValue(obj, instance); //注入依赖项
}
-
- if(_unfinishedDependencies.TryRemove(type.FullName, out unfinishedPropertyList))
+
+ if (_unfinishedDependencies.TryRemove(type.FullName, out unfinishedPropertyList))
{
unfinishedPropertyList.Clear();
}
@@ -272,19 +246,19 @@ namespace Serein.Library.Utils
else
{
// 存在依赖项,但目标类型的实例暂未加载,需要等待需要实例完成注册
- var unfinishedDependenciesList = _unfinishedDependencies.GetOrAdd(propertyType.FullName, _ = new List<(object, PropertyInfo)>());
+ var unfinishedDependenciesList = _unfinishedDependencies.GetOrAdd(propertyType.FullName, _ = new List<(object, PropertyInfo)>());
var data = (instance, property);
- if (!unfinishedDependenciesList.Contains(data))
- {
- unfinishedDependenciesList.Add(data);
- }
- isPass = false;
+ if (!unfinishedDependenciesList.Contains(data))
+ {
+ unfinishedDependenciesList.Add(data);
+ }
+ isPass = false;
}
}
return isPass;
}
-
+
///
/// 再次尝试注入目标实例的依赖项
///
@@ -304,10 +278,11 @@ namespace Serein.Library.Utils
}
}
}
- }
+ }
+ #endregion
#region run()
- public ISereinIoc Run(Action action)
+ public ISereinIOC Run(Action action)
{
var service = GetOrInstantiate();
if (service != null)
@@ -317,7 +292,7 @@ namespace Serein.Library.Utils
return this;
}
- public ISereinIoc Run(Action action)
+ public ISereinIOC Run(Action action)
{
var service1 = GetOrInstantiate();
var service2 = GetOrInstantiate();
@@ -326,7 +301,7 @@ namespace Serein.Library.Utils
return this;
}
- public ISereinIoc Run(Action action)
+ public ISereinIOC Run(Action action)
{
var service1 = GetOrInstantiate();
var service2 = GetOrInstantiate();
@@ -335,7 +310,7 @@ namespace Serein.Library.Utils
return this;
}
- public ISereinIoc Run(Action action)
+ public ISereinIOC Run(Action action)
{
var service1 = GetOrInstantiate();
var service2 = GetOrInstantiate();
@@ -345,7 +320,7 @@ namespace Serein.Library.Utils
return this;
}
- public ISereinIoc Run(Action action)
+ public ISereinIOC Run(Action action)
{
var service1 = GetOrInstantiate();
var service2 = GetOrInstantiate();
@@ -356,7 +331,7 @@ namespace Serein.Library.Utils
return this;
}
- public ISereinIoc Run(Action action)
+ public ISereinIOC Run(Action action)
{
var service1 = GetOrInstantiate();
var service2 = GetOrInstantiate();
@@ -368,7 +343,7 @@ namespace Serein.Library.Utils
return this;
}
- public ISereinIoc Run(Action action)
+ public ISereinIOC Run(Action action)
{
var service1 = GetOrInstantiate();
var service2 = GetOrInstantiate();
@@ -381,7 +356,7 @@ namespace Serein.Library.Utils
return this;
}
- public ISereinIoc Run(Action action)
+ public ISereinIOC Run(Action action)
{
var service1 = GetOrInstantiate();
var service2 = GetOrInstantiate();
diff --git a/NodeFlow/FlowEnvironment.cs b/NodeFlow/FlowEnvironment.cs
index 0b9a7e4..a865360 100644
--- a/NodeFlow/FlowEnvironment.cs
+++ b/NodeFlow/FlowEnvironment.cs
@@ -10,7 +10,9 @@ using System.Diagnostics;
using System.Net.Mime;
using System.Reflection;
using System.Reflection.Emit;
+using System.Text;
using System.Xml.Linq;
+using static Serein.NodeFlow.FlowStarter;
namespace Serein.NodeFlow
{
@@ -47,19 +49,28 @@ namespace Serein.NodeFlow
///
public event LoadDLLHandler OnDllLoad;
///
- /// 加载节点
+ /// 加载节点事件
///
public event LoadNodeHandler OnLoadNode;
///
- /// 连接节点
+ /// 节点连接属性改变事件
///
public event NodeConnectChangeHandler OnNodeConnectChange;
///
- /// 创建节点
+ /// 节点创建时间
///
public event NodeCreateHandler OnNodeCreate;
+ ///
+ /// 移除节点事件
+ ///
public event NodeRemoteHandler OnNodeRemote;
+ ///
+ /// 起始节点变化事件
+ ///
public event StartNodeChangeHandler OnStartNodeChange;
+ ///
+ /// 流程运行完成时间
+ ///
public event FlowRunCompleteHandler OnFlowRunComplete;
private FlowStarter? nodeFlowStarter = null;
@@ -72,7 +83,7 @@ namespace Serein.NodeFlow
///
/// 一种轻量的IOC容器
///
- public SereinIoc SereinIoc { get; } = new SereinIoc();
+ // public SereinIoc SereinIoc { get; } = new SereinIoc();
///
/// 存储加载的程序集路径
@@ -92,15 +103,17 @@ namespace Serein.NodeFlow
public Dictionary Nodes { get; } = [];
- public List Regions { get; } = [];
+ // public List Regions { get; } = [];
///
/// 存放触发器节点(运行时全部调用)
///
public List FlipflopNodes { get; } = [];
- private NodeModelBase? _startNode = null;
-
+ ///
+ /// 私有属性
+ ///
+ private NodeModelBase _startNode;
///
/// 起始节点
///
@@ -112,17 +125,12 @@ namespace Serein.NodeFlow
}
set
{
- if (_startNode is null)
- {
- value.IsStart = true;
- _startNode = value;
- }
- else
- {
+ if (_startNode is not null)
+ {
_startNode.IsStart = false;
- value.IsStart = true;
- _startNode = value;
}
+ value.IsStart = true;
+ _startNode = value;
}
}
@@ -132,19 +140,32 @@ namespace Serein.NodeFlow
///
public async Task StartAsync()
{
- nodeFlowStarter = new FlowStarter(SereinIoc);
- var nodes = Nodes.Values.ToList();
- var flipflopNodes = nodes.Where(it => it.MethodDetails?.MethodDynamicType == NodeType.Flipflop
- && it.IsStart == false)
- .Select(it => it as SingleFlipflopNode)
- .ToList();
+ nodeFlowStarter = new FlowStarter();
+ List flipflopNodes = Nodes.Values.Where(it => it.MethodDetails?.MethodDynamicType == NodeType.Flipflop && it.IsStart == false)
+ .Select(it => (SingleFlipflopNode)it)
+ .Where(node => node is SingleFlipflopNode flipflopNode && flipflopNode.NotExitPreviousNode())
+ .ToList();// 获取需要再运行开始之前启动的触发器节点
+ var runMethodDetailess = Nodes.Values.Select(item => item.MethodDetails).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();
+ await nodeFlowStarter.RunAsync(StartNode,
+ this,
+ runMethodDetailess,
+ initMethods,
+ loadingMethods,
+ exitMethods,
+ flipflopNodes);
- await nodeFlowStarter.RunAsync(StartNode, this, MethodDetailss, flipflopNodes);
+ if(nodeFlowStarter?.FlipFlopState == RunState.NoStart)
+ {
+ this.Exit(); // 未运行触发器时,才会调用结束方法
+ }
+ nodeFlowStarter = null;
}
public void Exit()
{
nodeFlowStarter?.Exit();
- nodeFlowStarter = null;
OnFlowRunComplete?.Invoke(new FlowEventArgs());
}
@@ -162,19 +183,6 @@ namespace Serein.NodeFlow
#region 对外暴露的接口
- ///
- /// 获取方法描述
- ///
- public bool TryGetMethodDetails(string name, out MethodDetails? md)
- {
- md = MethodDetailss.FirstOrDefault(it => it.MethodName == name);
- if (md == null)
- {
- return false;
- }
- return true;
- }
-
///
/// 加载项目文件
///
@@ -247,27 +255,34 @@ namespace Serein.NodeFlow
}
///
- /// 连接节点
+ /// 保存项目为项目文件
///
- /// 起始节点
- /// 目标节点
- /// 连接关系
- public void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
+ ///
+ public SereinOutputFileData SaveProject()
{
- // 获取起始节点与目标节点
- if (!Nodes.TryGetValue(fromNodeGuid, out NodeModelBase? fromNode) || !Nodes.TryGetValue(toNodeGuid, out NodeModelBase? toNode))
+ var projectData = new SereinOutputFileData()
{
- return;
- }
- if (fromNode is null || toNode is null)
+ Librarys = LoadedAssemblies.Select(assemblies => assemblies.ToLibrary()).ToArray(),
+ Nodes = Nodes.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
+ StartNode = Nodes.Values.FirstOrDefault(it => it.IsStart)?.Guid,
+ };
+ return projectData;
+ }
+ ///
+ /// 从文件路径中加载DLL
+ ///
+ ///
+ ///
+ public void LoadDll(string dllPath)
+ {
+ (var assembly, var list) = LoadAssembly(dllPath);
+ if (assembly is not null && list.Count > 0)
{
- return;
+ MethodDetailss.AddRange(list);
+ OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list));
}
- // 开始连接
- ConnectNode(fromNode, toNode, connectionType); // 外部调用连接方法
}
-
///
/// 创建节点
///
@@ -326,66 +341,6 @@ namespace Serein.NodeFlow
SetStartNode(nodeBase);
}
}
-
-
- ///
- /// 从文件路径中加载DLL
- ///
- ///
- ///
- public void LoadDll(string dllPath)
- {
- (var assembly, var list) = LoadAssembly(dllPath);
- if (assembly is not null && list.Count > 0)
- {
- MethodDetailss.AddRange(list);
- OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list));
- }
-
- }
-
- ///
- /// 保存项目为项目文件
- ///
- ///
- public SereinOutputFileData SaveProject()
- {
- var projectData = new SereinOutputFileData()
- {
- Librarys = LoadedAssemblies.Select(assemblies => assemblies.ToLibrary()).ToArray(),
- Nodes = Nodes.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
- StartNode = Nodes.Values.FirstOrDefault(it => it.IsStart)?.Guid,
- };
- return projectData;
- }
-
- ///
- /// 移除连接关系
- ///
- ///
- ///
- ///
- ///
- public void RemoteConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
- {
- // 获取起始节点与目标节点
- if (!Nodes.TryGetValue(fromNodeGuid, out NodeModelBase? fromNode) || !Nodes.TryGetValue(toNodeGuid, out NodeModelBase? toNode))
- {
- return;
- }
- if (fromNode is null || toNode is null)
- {
- return;
- }
-
- fromNode.SuccessorNodes[connectionType].Remove(toNode);
- toNode.PreviousNodes[connectionType].Remove(fromNode);
- OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
- toNodeGuid,
- connectionType,
- NodeConnectChangeEventArgs.ChangeTypeEnum.Remote));
- }
-
///
/// 移除节点
///
@@ -418,7 +373,7 @@ namespace Serein.NodeFlow
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(pNode.Guid,
remoteNode.Guid,
pCType,
- NodeConnectChangeEventArgs.ChangeTypeEnum.Remote)); // 通知UI
+ NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI
}
}
@@ -433,7 +388,7 @@ namespace Serein.NodeFlow
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(remoteNode.Guid,
sNode.Guid,
sCType,
- NodeConnectChangeEventArgs.ChangeTypeEnum.Remote)); // 通知UI
+ NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI
}
}
@@ -443,6 +398,68 @@ namespace Serein.NodeFlow
OnNodeRemote?.Invoke(new NodeRemoteEventArgs(nodeGuid));
}
+ ///
+ /// 连接节点
+ ///
+ /// 起始节点
+ /// 目标节点
+ /// 连接关系
+ public void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
+ {
+ // 获取起始节点与目标节点
+ if (!Nodes.TryGetValue(fromNodeGuid, out NodeModelBase? fromNode) || !Nodes.TryGetValue(toNodeGuid, out NodeModelBase? toNode))
+ {
+ return;
+ }
+ if (fromNode is null || toNode is null)
+ {
+ return;
+ }
+ // 开始连接
+ ConnectNode(fromNode, toNode, connectionType); // 外部调用连接方法
+
+ }
+
+ ///
+ /// 移除连接关系
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void RemoteConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
+ {
+ // 获取起始节点与目标节点
+ if (!Nodes.TryGetValue(fromNodeGuid, out NodeModelBase? fromNode) || !Nodes.TryGetValue(toNodeGuid, out NodeModelBase? toNode))
+ {
+ return;
+ }
+ if (fromNode is null || toNode is null)
+ {
+ return;
+ }
+
+ fromNode.SuccessorNodes[connectionType].Remove(toNode);
+ toNode.PreviousNodes[connectionType].Remove(fromNode);
+ OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
+ toNodeGuid,
+ connectionType,
+ NodeConnectChangeEventArgs.ConnectChangeType.Remote));
+ }
+
+ ///
+ /// 获取方法描述
+ ///
+ public bool TryGetMethodDetails(string name, out MethodDetails? md)
+ {
+ md = MethodDetailss.FirstOrDefault(it => it.MethodName == name);
+ if (md == null)
+ {
+ return false;
+ }
+ return true;
+ }
+
///
/// 设置起点控件
///
@@ -494,14 +511,14 @@ namespace Serein.NodeFlow
{
// 加载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);
+ //foreach (var md in itemMethodDetails)
+ //{
+ // // var instanceType =
+ // // Activator.CreateInstance(md.ActingInstanceType);
+ // // SereinIoc.RegisterInstantiate(md.ActingInstance);
+ // SereinIoc.Register(md.ActingInstanceType);
+ //}
}
LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中
LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径
@@ -514,7 +531,6 @@ namespace Serein.NodeFlow
}
}
-
///
/// 连接节点
///
@@ -573,7 +589,7 @@ namespace Serein.NodeFlow
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNode.Guid,
toNode.Guid,
connectionType,
- NodeConnectChangeEventArgs.ChangeTypeEnum.Create)); // 通知UI
+ NodeConnectChangeEventArgs.ConnectChangeType.Create)); // 通知UI
}
///
@@ -589,20 +605,11 @@ namespace Serein.NodeFlow
}
#endregion
- #region 视觉元素交互
-
- #region 本地交互(WPF)
+ #region 网络交互
#endregion
- #region 网络交互(通过Socket的方式进行操作)
-
- #endregion
-
-
- #endregion
-
-}
+ }
public static class FlowFunc
{
public static Library.Entity.Library ToLibrary(this Assembly assembly)
@@ -625,6 +632,22 @@ namespace Serein.NodeFlow
_ => throw new NotImplementedException("未定义的流程状态")
};
}
+
+ public static bool NotExitPreviousNode(this SingleFlipflopNode node)
+ {
+ ConnectionType[] ct = [ConnectionType.IsSucceed,
+ ConnectionType.IsFail,
+ ConnectionType.IsError,
+ ConnectionType.Upstream];
+ foreach (ConnectionType ctType in ct)
+ {
+ if(node.PreviousNodes[ctType].Count > 0)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/NodeFlow/FlowStarter.cs b/NodeFlow/FlowStarter.cs
index 8943f31..da72a72 100644
--- a/NodeFlow/FlowStarter.cs
+++ b/NodeFlow/FlowStarter.cs
@@ -16,69 +16,135 @@ namespace Serein.NodeFlow
///
public class FlowStarter
{
- public FlowStarter(ISereinIoc serviceContainer/*, List methodDetails*/)
+ public FlowStarter()
{
- SereinIoc = serviceContainer;
-
+ 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;
+
- 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; }
///
/// 开始运行
///
- ///
+ /// 起始节点
+ /// 运行环境
+ /// 环境中已加载的所有节点方法
+ /// 触发器节点
///
- // public async Task RunAsync(List nodes, IFlowEnvironment flowEnvironment)
- public async Task RunAsync(NodeModelBase startNode, IFlowEnvironment flowEnvironment, List methodDetailss, List flipflopNodes)
+ public async Task RunAsync(NodeModelBase startNode,
+ IFlowEnvironment env,
+ List runMd,
+ List initMethods,
+ List loadingMethods,
+ List exitMethods,
+ List flipflopNodes)
{
- // var startNode = nodes.FirstOrDefault(p => p.IsStart);
- if (startNode == null) { return; }
+
+ FlowState = RunState.Running; // 开始运行
+ if (startNode == null) {
+ FlowState = RunState.Completion; // 不存在起点,退出流程
+ return;
+ }
+
+ // 判断使用哪一种流程上下文
var isNetFramework = true;
-
if (isNetFramework)
{
- Context = new Serein.Library.Framework.NodeFlow.DynamicContext(SereinIoc, flowEnvironment);
+ Context = new Serein.Library.Framework.NodeFlow.DynamicContext(SereinIOC, env);
}
else
{
- Context = new Serein.Library.Core.NodeFlow.DynamicContext(SereinIoc, flowEnvironment);
+ Context = new Serein.Library.Core.NodeFlow.DynamicContext(SereinIOC, env);
}
- MainCts = SereinIoc.GetOrCreateServiceInstance();
-
- foreach (var md in methodDetailss)
+ #region 初始化运行环境的Ioc容器
+ // 清除节点使用的对象
+ foreach (var nodeMd in runMd)
{
- SereinIoc.Register(md.ActingInstanceType);
+ nodeMd.ActingInstance = null;
}
- SereinIoc.Build();
- foreach (var md in flipflopNodes.Select(it => it.MethodDetails).ToArray())
+ SereinIOC.Reset(); // 开始运行时清空ioc中注册的实例
+ // 初始化ioc容器中的类型对象
+ foreach (var md in runMd)
{
- md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType);
+ SereinIOC.Register(md.ActingInstanceType);
}
- foreach (var md in methodDetailss)
+ SereinIOC.Build();
+ foreach (var md in runMd)
{
- md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType);
+ md.ActingInstance = SereinIOC.GetOrInstantiate(md.ActingInstanceType);
}
- 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();
+ //foreach (var md in flipflopNodes.Select(it => it.MethodDetails).ToArray())
+ //{
+ // md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType);
+ //}
+ #endregion
+
+
+ #region 创建Node中初始化、加载时、退出时调用的方法
+
+ foreach (var md in initMethods) // 初始化
+ {
+ md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
+ }
+ foreach (var md in loadingMethods) // 加载
+ {
+ md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
+ }
+ foreach (var md in exitMethods) // 初始化
+ {
+ md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
+ }
+
+ object?[]? args = [Context];
ExitAction = () =>
{
- //ServiceContainer.Run((web) =>
- //{
- // web?.Stop();
- //});
foreach (MethodDetails? md in exitMethods)
{
- md.ActingInstance = Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
- object?[]? args = [Context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
@@ -86,53 +152,62 @@ namespace Serein.NodeFlow
{
Context.NodeRunCts.Cancel();
}
- if (MainCts != null && !MainCts.IsCancellationRequested) MainCts.Cancel();
- SereinIoc.Reset();
+ if (FlipFlopCts != null && !FlipFlopCts.IsCancellationRequested)
+ {
+ FlipFlopCts.Cancel();
+ }
+ FlowState = RunState.Completion;
+ FlipFlopState = RunState.Completion;
};
Context.SereinIoc.Build();
+ #endregion
+
+ #region 执行初始化,然后绑定IOC容器,再执行加载时
+
foreach (var md in initMethods) // 初始化 - 调用方法
{
- md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
- object?[]? args = [Context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
Context.SereinIoc.Build();
foreach (var md in loadingMethods) // 加载
{
- md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
- object?[]? args = [Context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
- }
+ }
+ #endregion
- // 运行触发器节点
- var singleFlipflopNodes = flipflopNodes.Select(it => (SingleFlipflopNode)it).ToArray();
-
- // 使用 TaskCompletionSource 创建未启动的任务
- var tasks = singleFlipflopNodes.Select(async node =>
- {
- await FlipflopExecute(node, flowEnvironment);
- }).ToArray();
- _ = Task.WhenAll(tasks);
+
+ // 节点任务的启动
try
{
- await Task.Run(async () =>
+
+ if (flipflopNodes.Count > 0)
{
- await startNode.StartExecution(Context);
- //await Task.WhenAll([startNode.StartExecution(Context), .. tasks]);
- });
+ FlipFlopState = RunState.Running;
+ // 如果存在需要启动的触发器,则开始启动
+ FlipFlopCts = SereinIOC.GetOrInstantiate();
+ // 使用 TaskCompletionSource 创建未启动的触发器任务
+ var tasks = flipflopNodes.Select(async node =>
+ {
+ await FlipflopExecute(node, env);
+ }).ToArray();
+ _ = Task.WhenAll(tasks);
+ }
+ await startNode.StartExecution(Context);
// 等待结束
- while (!MainCts.IsCancellationRequested)
+ if(FlipFlopCts != null)
{
- await Task.Delay(100);
+ while (!FlipFlopCts.IsCancellationRequested)
+ {
+ await Task.Delay(100);
+ }
}
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
}
-
}
///
@@ -140,17 +215,15 @@ namespace Serein.NodeFlow
///
private async Task FlipflopExecute(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment flowEnvironment)
{
- DynamicContext context = new DynamicContext(SereinIoc, flowEnvironment);
+ DynamicContext context = new DynamicContext(SereinIOC, flowEnvironment);
MethodDetails md = singleFlipFlopNode.MethodDetails;
var del = md.MethodDelegate;
try
{
-
-
//var func = md.ExplicitDatas.Length == 0 ? (Func