mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-25 09:26:34 +08:00
IOC容器添加构造函数注入(DLL类中使用AutoRegisterAttribute特性标注的类,会在流程启动时自动注册),提高可读性。
This commit is contained in:
@@ -24,7 +24,7 @@ namespace Serein.Library.Core.NodeFlow
|
|||||||
{
|
{
|
||||||
if (NodeRunCts == null)
|
if (NodeRunCts == null)
|
||||||
{
|
{
|
||||||
NodeRunCts = Env.IOC.GetOrRegisterInstantiate<NodeRunCts>();
|
NodeRunCts = Env.IOC.Get<NodeRunCts>();
|
||||||
}
|
}
|
||||||
// 使用局部变量,避免捕获外部的 `action`
|
// 使用局部变量,避免捕获外部的 `action`
|
||||||
Action localAction = action;
|
Action localAction = action;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Serein.Library.Framework.NodeFlow
|
|||||||
{
|
{
|
||||||
if(NodeRunCts == null)
|
if(NodeRunCts == null)
|
||||||
{
|
{
|
||||||
NodeRunCts = Env.IOC.GetOrRegisterInstantiate<NodeRunCts>();
|
NodeRunCts = Env.IOC.Get<NodeRunCts>();
|
||||||
}
|
}
|
||||||
// 使用局部变量,避免捕获外部的 `action`
|
// 使用局部变量,避免捕获外部的 `action`
|
||||||
Action localAction = action;
|
Action localAction = action;
|
||||||
|
|||||||
@@ -24,7 +24,13 @@ namespace Serein.Library.Api
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载项目文件时成功加载了DLL文件
|
/// 加载项目文件时成功加载了DLL文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public delegate void LoadDLLHandler(LoadDLLEventArgs eventArgs);
|
public delegate void LoadDllHandler(LoadDllEventArgs eventArgs);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除了加载的dll
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventArgs"></param>
|
||||||
|
public delegate void RemoteDllHandler(RemoteDllEventArgs eventArgs);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 运行环境节点连接发生了改变
|
/// 运行环境节点连接发生了改变
|
||||||
@@ -110,23 +116,30 @@ namespace Serein.Library.Api
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoadDLLEventArgs : FlowEventArgs
|
public class LoadDllEventArgs : FlowEventArgs
|
||||||
{
|
{
|
||||||
public LoadDLLEventArgs(Assembly Assembly, List<MethodDetails> MethodDetailss)
|
public LoadDllEventArgs(NodeLibrary nodeLibrary, List<MethodDetails> MethodDetailss)
|
||||||
{
|
{
|
||||||
this.Assembly = Assembly;
|
this.NodeLibrary = nodeLibrary;
|
||||||
this.MethodDetailss = MethodDetailss;
|
this.MethodDetailss = MethodDetailss;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已加载了的程序集
|
/// 已加载了的程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Assembly Assembly { get; protected set; }
|
public NodeLibrary NodeLibrary { get; protected set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// dll文件中有效的流程方法描述
|
/// dll文件中有效的流程方法描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<MethodDetails> MethodDetailss { get; protected set; }
|
public List<MethodDetails> MethodDetailss { get; protected set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class RemoteDllEventArgs : FlowEventArgs
|
||||||
|
{
|
||||||
|
public RemoteDllEventArgs()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public class NodeConnectChangeEventArgs : FlowEventArgs
|
public class NodeConnectChangeEventArgs : FlowEventArgs
|
||||||
{
|
{
|
||||||
@@ -385,7 +398,7 @@ namespace Serein.Library.Api
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载Dll
|
/// 加载Dll
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event LoadDLLHandler OnDllLoad;
|
event LoadDllHandler OnDllLoad;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 项目加载完成
|
/// 项目加载完成
|
||||||
@@ -455,6 +468,8 @@ namespace Serein.Library.Api
|
|||||||
bool TryGetMethodDetails(string methodName, out MethodDetails md);
|
bool TryGetMethodDetails(string methodName, out MethodDetails md);
|
||||||
|
|
||||||
|
|
||||||
|
bool TryGetDelegate(string methodName, out Delegate del);
|
||||||
|
|
||||||
//bool TryGetNodeData(string methodName, out NodeData node);
|
//bool TryGetNodeData(string methodName, out NodeData node);
|
||||||
|
|
||||||
#region 环境基础接口
|
#region 环境基础接口
|
||||||
@@ -475,6 +490,12 @@ namespace Serein.Library.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dllPath"></param>
|
/// <param name="dllPath"></param>
|
||||||
void LoadDll(string dllPath);
|
void LoadDll(string dllPath);
|
||||||
|
/// <summary>
|
||||||
|
/// 移除DLL
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dllPath"></param>
|
||||||
|
bool RemoteDll(string assemblyFullName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清理加载的DLL(待更改)
|
/// 清理加载的DLL(待更改)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -30,20 +30,21 @@ namespace Serein.Library.Api
|
|||||||
/// <param name="parameters"></param>
|
/// <param name="parameters"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ISereinIOC Register<TService, TImplementation>(params object[] parameters) where TImplementation : TService;
|
ISereinIOC Register<TService, TImplementation>(params object[] parameters) where TImplementation : TService;
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// 获取或创建并注入目标类型,会记录到IOC容器中。
|
///// 获取或创建并注入目标类型,会记录到IOC容器中。
|
||||||
/// </summary>
|
///// </summary>
|
||||||
T GetOrRegisterInstantiate<T>();
|
//T GetOrRegisterInstantiate<T>();
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// 获取或创建并注入目标类型,会记录到IOC容器中。
|
///// 获取或创建并注入目标类型,会记录到IOC容器中。
|
||||||
/// </summary>
|
///// </summary>
|
||||||
object GetOrRegisterInstantiate(Type type);
|
//object GetOrRegisterInstantiate(Type type);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取类型的实例
|
/// 获取类型的实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type"></param>
|
/// <param name="type"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
object Get(Type type);
|
object Get(Type type);
|
||||||
|
T Get<T>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定名称的实例
|
/// 获取指定名称的实例
|
||||||
@@ -64,8 +65,11 @@ namespace Serein.Library.Api
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用于临时实例的创建,不注册到IOC容器中,依赖项注入失败时也不记录。
|
/// 用于临时实例的创建,不注册到IOC容器中,依赖项注入失败时也不记录。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
object Instantiate(Type type, params object[] parameters);
|
object Instantiate(Type type);
|
||||||
|
/// <summary>
|
||||||
|
/// 用于临时实例的创建,不注册到IOC容器中,依赖项注入失败时也不记录。
|
||||||
|
/// </summary>
|
||||||
|
T Instantiate<T>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实例化注册的类型,并注入依赖项
|
/// 实例化注册的类型,并注入依赖项
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ namespace Serein.Library.Entity
|
|||||||
{
|
{
|
||||||
ActingInstance = ActingInstance,
|
ActingInstance = ActingInstance,
|
||||||
ActingInstanceType = ActingInstanceType,
|
ActingInstanceType = ActingInstanceType,
|
||||||
MethodDelegate = MethodDelegate,
|
|
||||||
MethodDynamicType = MethodDynamicType,
|
MethodDynamicType = MethodDynamicType,
|
||||||
MethodGuid = Guid.NewGuid().ToString(),
|
MethodGuid = Guid.NewGuid().ToString(),
|
||||||
MethodTips = MethodTips,
|
MethodTips = MethodTips,
|
||||||
@@ -68,8 +67,7 @@ namespace Serein.Library.Entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 方法委托
|
/// 方法委托
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// public Delegate MethodDelegate { get; set; }
|
||||||
public Delegate MethodDelegate { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 节点类型
|
/// 节点类型
|
||||||
|
|||||||
14
Library/Entity/NodeLibrary.cs
Normal file
14
Library/Entity/NodeLibrary.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Serein.Library.Entity
|
||||||
|
{
|
||||||
|
public class NodeLibrary
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public Assembly Assembly { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,10 +9,10 @@ namespace Serein.Library.Attributes
|
|||||||
[AttributeUsage(AttributeTargets.Property)]
|
[AttributeUsage(AttributeTargets.Property)]
|
||||||
public sealed class AutoInjectionAttribute : Attribute
|
public sealed class AutoInjectionAttribute : Attribute
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 表示该类自动注册
|
/// 表示该类自动注册(单例模式)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public sealed class AutoRegisterAttribute : Attribute
|
public sealed class AutoRegisterAttribute : Attribute
|
||||||
@@ -20,7 +20,7 @@ namespace Serein.Library.Attributes
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用来判断一个类是否需要注册并构建实例(单例模式场景使用)
|
/// 用来判断一个类是否需要注册并构建节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class DynamicFlowAttribute : Attribute
|
public class DynamicFlowAttribute : Attribute
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using System.Xml.Schema;
|
||||||
|
|
||||||
namespace Serein.Library.Utils
|
namespace Serein.Library.Utils
|
||||||
{
|
{
|
||||||
@@ -43,10 +44,14 @@ namespace Serein.Library.Utils
|
|||||||
_unfinishedDependencies = new ConcurrentDictionary<string, List<(object, PropertyInfo)>>();
|
_unfinishedDependencies = new ConcurrentDictionary<string, List<(object, PropertyInfo)>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 绑定之前进行的默认绑定
|
||||||
|
/// </summary>
|
||||||
public void InitRegister()
|
public void InitRegister()
|
||||||
{
|
{
|
||||||
//_dependencies[typeof(ISereinIOC).FullName] = this;
|
_dependencies[typeof(ISereinIOC).FullName] = this;
|
||||||
Register<IRouter, Router>();
|
Register<IRouter, Router>();
|
||||||
|
|
||||||
//foreach (var type in _typeMappings.Values)
|
//foreach (var type in _typeMappings.Values)
|
||||||
//{
|
//{
|
||||||
// Register(type);
|
// Register(type);
|
||||||
@@ -91,47 +96,47 @@ namespace Serein.Library.Utils
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。
|
/// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T GetOrRegisterInstantiate<T>()
|
//public T GetOrRegisterInstantiate<T>()
|
||||||
{
|
//{
|
||||||
return (T)GetOrRegisterInstantiate(typeof(T));
|
// return (T)GetOrRegisterInstantiate(typeof(T));
|
||||||
}
|
//}
|
||||||
|
|
||||||
/// <summary>
|
///// <summary>
|
||||||
/// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。
|
///// 尝试从容器中获取对象,如果不存在目标类型的对象,则将类型信息登记到容器,并实例化注入依赖项。如果依然无法注册,则返回null。
|
||||||
/// </summary>
|
///// </summary>
|
||||||
public object GetOrRegisterInstantiate(Type type)
|
//public object GetOrRegisterInstantiate(Type type)
|
||||||
{
|
//{
|
||||||
// 尝试从容器中获取对象
|
// // 尝试从容器中获取对象
|
||||||
if (!_dependencies.TryGetValue(type.FullName, out object value))
|
// if (!_dependencies.TryGetValue(type.FullName, out object value))
|
||||||
{
|
// {
|
||||||
// 容器中不存在目标类型的对象
|
// // 容器中不存在目标类型的对象
|
||||||
if (type.IsInterface)
|
// if (type.IsInterface)
|
||||||
{
|
// {
|
||||||
if (_typeMappings.TryGetValue(type.FullName, out Type implementationType))
|
// if (_typeMappings.TryGetValue(type.FullName, out Type implementationType))
|
||||||
{
|
// {
|
||||||
// 是接口类型,存在注册信息
|
// // 是接口类型,存在注册信息
|
||||||
Register(type);// 注册类型信息
|
// Register(type);// 注册类型信息
|
||||||
value = Instantiate(implementationType); // 创建实例对象,并注入依赖
|
// value = Instantiate(implementationType); // 创建实例对象,并注入依赖
|
||||||
CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中
|
// CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中
|
||||||
_typeMappings.TryRemove(type.FullName, out _); // 取消类型的注册信息
|
// _typeMappings.TryRemove(type.FullName, out _); // 取消类型的注册信息
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
//需要获取接口类型的实例,但不存在类型注册信息
|
// //需要获取接口类型的实例,但不存在类型注册信息
|
||||||
Console.WriteLine("当前需要获取接口,但没有注册实现类的类型,无法创建接口实例");
|
// Console.WriteLine("当前需要获取接口,但没有注册实现类的类型,无法创建接口实例");
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
// 不是接口,直接注册
|
// // 不是接口,直接注册
|
||||||
Register(type);// 注册类型信息
|
// Register(type);// 注册类型信息
|
||||||
value = Instantiate(type); // 创建实例对象,并注入依赖
|
// value = Instantiate(type); // 创建实例对象,并注入依赖
|
||||||
CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中
|
// CustomRegisterInstance(type.FullName, value);// 登记到IOC容器中
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return value;
|
// return value;
|
||||||
}
|
//}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用于临时实例的创建,不登记到IOC容器中,依赖项注入失败时也不记录。
|
/// 用于临时实例的创建,不登记到IOC容器中,依赖项注入失败时也不记录。
|
||||||
@@ -139,16 +144,25 @@ namespace Serein.Library.Utils
|
|||||||
/// <param name="controllerType"></param>
|
/// <param name="controllerType"></param>
|
||||||
/// <param name="parameters"></param>
|
/// <param name="parameters"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public object Instantiate(Type controllerType, params object[] parameters)
|
public object Instantiate(Type type)
|
||||||
{
|
{
|
||||||
var instance = Activator.CreateInstance(controllerType, parameters); // CreateInstance(controllerType, parameters); // 创建目标类型的实例
|
var constructor = type.GetConstructors().First(); // 获取第一个构造函数
|
||||||
|
var parameters = constructor.GetParameters(); // 获取参数列表
|
||||||
|
var parameterValues = parameters.Select(param => ResolveDependency(param.ParameterType)).ToArray();
|
||||||
|
var instance = Activator.CreateInstance(type, parameterValues);
|
||||||
|
|
||||||
|
//var instance =CreateInstance(controllerType, parameters); // CreateInstance(controllerType, parameters); // 创建目标类型的实例
|
||||||
if (instance != null)
|
if (instance != null)
|
||||||
{
|
{
|
||||||
InjectDependencies(instance, false); // 完成创建后注入实例需要的依赖项
|
InjectDependencies(instance, false); // 完成创建后注入实例需要的特性依赖项
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T Instantiate<T>()
|
||||||
|
{
|
||||||
|
return (T)Instantiate(typeof(T));
|
||||||
|
}
|
||||||
#region 通过名称记录或获取一个实例
|
#region 通过名称记录或获取一个实例
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -177,15 +191,17 @@ namespace Serein.Library.Utils
|
|||||||
return Get(type.FullName);
|
return Get(type.FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T Get<T>()
|
||||||
|
{
|
||||||
|
return (T)Get(typeof(T).FullName);
|
||||||
|
}
|
||||||
public T Get<T>(string name)
|
public T Get<T>(string name)
|
||||||
{
|
{
|
||||||
return (T)Get(name);
|
return (T)Get(name);
|
||||||
}
|
}
|
||||||
private object Get(string name)
|
private object Get(string name)
|
||||||
{
|
{
|
||||||
object value;
|
if (!_dependencies.TryGetValue(name, out object value))
|
||||||
if (!_dependencies.TryGetValue(name, out value))
|
|
||||||
{
|
{
|
||||||
value = null;
|
value = null;
|
||||||
}
|
}
|
||||||
@@ -194,9 +210,6 @@ namespace Serein.Library.Utils
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region 容器管理(清空,绑定)
|
#region 容器管理(清空,绑定)
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -224,9 +237,9 @@ namespace Serein.Library.Utils
|
|||||||
/// 实例化所有已注册的类型,并尝试绑定
|
/// 实例化所有已注册的类型,并尝试绑定
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool Build()
|
public bool Build2()
|
||||||
{
|
{
|
||||||
InitRegister();
|
InitRegister();
|
||||||
// 遍历已注册类型
|
// 遍历已注册类型
|
||||||
foreach (var type in _typeMappings.Values.ToArray())
|
foreach (var type in _typeMappings.Values.ToArray())
|
||||||
{
|
{
|
||||||
@@ -245,7 +258,105 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Build()
|
||||||
|
{
|
||||||
|
InitRegister();
|
||||||
|
var graph = new Dictionary<string, List<Type>>();
|
||||||
|
//var graph = new Dictionary<string, List<string>>();
|
||||||
|
|
||||||
|
// 构建依赖关系图
|
||||||
|
foreach (var type in _typeMappings.Values)
|
||||||
|
{
|
||||||
|
var constructor = type.GetConstructors()
|
||||||
|
.OrderByDescending(c => c.GetParameters().Length)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
var parameters = constructor.GetParameters();
|
||||||
|
foreach (var param in parameters)
|
||||||
|
{
|
||||||
|
var paramTypeName = param.ParameterType.FullName;
|
||||||
|
if (!graph.ContainsKey(paramTypeName))
|
||||||
|
{
|
||||||
|
graph[paramTypeName] = new List<Type>();
|
||||||
|
}
|
||||||
|
graph[paramTypeName].Add(type); // 使用 Type 而不是字符串
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行拓扑排序
|
||||||
|
var sortedTypes = TopologicalSort(graph);
|
||||||
|
|
||||||
|
// 创建实例并注册
|
||||||
|
foreach (var type in sortedTypes)
|
||||||
|
{
|
||||||
|
var typeName = type.FullName;
|
||||||
|
if (!_dependencies.ContainsKey(typeName))
|
||||||
|
{
|
||||||
|
|
||||||
|
var value = CreateInstance(type);
|
||||||
|
CustomRegisterInstance(typeName, value);
|
||||||
|
//if (graph.ContainsKey(typeName))
|
||||||
|
//{
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// Console.WriteLine("error:"+typeName);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("not create:" + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行拓扑排序
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="graph"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private List<Type> TopologicalSort(Dictionary<string, List<Type>> graph)
|
||||||
|
{
|
||||||
|
var sorted = new List<Type>();
|
||||||
|
var visited = new HashSet<string>();
|
||||||
|
|
||||||
|
void Visit(Type node)
|
||||||
|
{
|
||||||
|
var nodeName = node.FullName;
|
||||||
|
if (visited.Contains(nodeName)) return;
|
||||||
|
visited.Add(nodeName);
|
||||||
|
if (graph.TryGetValue(nodeName, out var neighbors))
|
||||||
|
{
|
||||||
|
foreach (var neighbor in neighbors)
|
||||||
|
{
|
||||||
|
Visit(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sorted.Add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var node in graph.Keys)
|
||||||
|
{
|
||||||
|
if (!_dependencies.ContainsKey(node))
|
||||||
|
{
|
||||||
|
var type = _typeMappings[node]; // 获取对应的 Type
|
||||||
|
Visit(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sorted.Reverse(); // 反转以得到正确顺序
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 私有方法
|
#region 私有方法
|
||||||
@@ -272,13 +383,29 @@ namespace Serein.Library.Utils
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建实例时,尝试注入到由ioc容器管理、并需要此实例的对象。
|
/// 创建实例时,尝试注入到由ioc容器管理、并需要此实例的对象。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private object CreateInstance(Type type, params object[] parameters)
|
private object CreateInstance(Type type)
|
||||||
{
|
{
|
||||||
var instance = Activator.CreateInstance(type);
|
var constructor = type.GetConstructors().First(); // 获取第一个构造函数
|
||||||
|
var parameters = constructor.GetParameters(); // 获取参数列表
|
||||||
|
var parameterValues = parameters.Select(param => ResolveDependency(param.ParameterType)).ToArray();
|
||||||
|
var instance = Activator.CreateInstance(type, parameterValues);
|
||||||
InjectUnfinishedDependencies(type.FullName, instance);
|
InjectUnfinishedDependencies(type.FullName, instance);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object ResolveDependency(Type parameterType)
|
||||||
|
{
|
||||||
|
var obj = Get(parameterType);
|
||||||
|
if (obj is null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"构造函数注入时类型[{parameterType}]不存在实例");
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 如果其它实例想要该对象时,注入过去
|
||||||
|
/// </summary>
|
||||||
private void InjectUnfinishedDependencies(string key,object instance)
|
private void InjectUnfinishedDependencies(string key,object instance)
|
||||||
{
|
{
|
||||||
if (_unfinishedDependencies.TryGetValue(key, out var unfinishedPropertyList))
|
if (_unfinishedDependencies.TryGetValue(key, out var unfinishedPropertyList))
|
||||||
@@ -379,7 +506,7 @@ namespace Serein.Library.Utils
|
|||||||
|
|
||||||
public void Run<T>(Action<T> action)
|
public void Run<T>(Action<T> action)
|
||||||
{
|
{
|
||||||
var service = GetOrRegisterInstantiate<T>();
|
var service = Get<T>();
|
||||||
if (service != null)
|
if (service != null)
|
||||||
{
|
{
|
||||||
action(service);
|
action(service);
|
||||||
@@ -388,72 +515,72 @@ namespace Serein.Library.Utils
|
|||||||
|
|
||||||
public void Run<T1, T2>(Action<T1, T2> action)
|
public void Run<T1, T2>(Action<T1, T2> action)
|
||||||
{
|
{
|
||||||
var service1 = GetOrRegisterInstantiate<T1>();
|
var service1 = Get<T1>();
|
||||||
var service2 = GetOrRegisterInstantiate<T2>();
|
var service2 = Get<T2>();
|
||||||
|
|
||||||
action(service1, service2);
|
action(service1, service2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run<T1, T2, T3>(Action<T1, T2, T3> action)
|
public void Run<T1, T2, T3>(Action<T1, T2, T3> action)
|
||||||
{
|
{
|
||||||
var service1 = GetOrRegisterInstantiate<T1>();
|
var service1 = Get<T1>();
|
||||||
var service2 = GetOrRegisterInstantiate<T2>();
|
var service2 = Get<T2>();
|
||||||
var service3 = GetOrRegisterInstantiate<T3>();
|
var service3 = Get<T3>();
|
||||||
action(service1, service2, service3);
|
action(service1, service2, service3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action)
|
public void Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action)
|
||||||
{
|
{
|
||||||
var service1 = GetOrRegisterInstantiate<T1>();
|
var service1 = Get<T1>();
|
||||||
var service2 = GetOrRegisterInstantiate<T2>();
|
var service2 = Get<T2>();
|
||||||
var service3 = GetOrRegisterInstantiate<T3>();
|
var service3 = Get<T3>();
|
||||||
var service4 = GetOrRegisterInstantiate<T4>();
|
var service4 = Get<T4>();
|
||||||
action(service1, service2, service3, service4);
|
action(service1, service2, service3, service4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action)
|
public void Run<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action)
|
||||||
{
|
{
|
||||||
var service1 = GetOrRegisterInstantiate<T1>();
|
var service1 = Get<T1>();
|
||||||
var service2 = GetOrRegisterInstantiate<T2>();
|
var service2 = Get<T2>();
|
||||||
var service3 = GetOrRegisterInstantiate<T3>();
|
var service3 = Get<T3>();
|
||||||
var service4 = GetOrRegisterInstantiate<T4>();
|
var service4 = Get<T4>();
|
||||||
var service5 = GetOrRegisterInstantiate<T5>();
|
var service5 = Get<T5>();
|
||||||
action(service1, service2, service3, service4, service5);
|
action(service1, service2, service3, service4, service5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action)
|
public void Run<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action)
|
||||||
{
|
{
|
||||||
var service1 = GetOrRegisterInstantiate<T1>();
|
var service1 = Get<T1>();
|
||||||
var service2 = GetOrRegisterInstantiate<T2>();
|
var service2 = Get<T2>();
|
||||||
var service3 = GetOrRegisterInstantiate<T3>();
|
var service3 = Get<T3>();
|
||||||
var service4 = GetOrRegisterInstantiate<T4>();
|
var service4 = Get<T4>();
|
||||||
var service5 = GetOrRegisterInstantiate<T5>();
|
var service5 = Get<T5>();
|
||||||
var service6 = GetOrRegisterInstantiate<T6>();
|
var service6 = Get<T6>();
|
||||||
action(service1, service2, service3, service4, service5, service6);
|
action(service1, service2, service3, service4, service5, service6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run<T1, T2, T3, T4, T5, T6, T7>(Action<T1, T2, T3, T4, T5, T6, T7> action)
|
public void Run<T1, T2, T3, T4, T5, T6, T7>(Action<T1, T2, T3, T4, T5, T6, T7> action)
|
||||||
{
|
{
|
||||||
var service1 = GetOrRegisterInstantiate<T1>();
|
var service1 = Get<T1>();
|
||||||
var service2 = GetOrRegisterInstantiate<T2>();
|
var service2 = Get<T2>();
|
||||||
var service3 = GetOrRegisterInstantiate<T3>();
|
var service3 = Get<T3>();
|
||||||
var service4 = GetOrRegisterInstantiate<T4>();
|
var service4 = Get<T4>();
|
||||||
var service5 = GetOrRegisterInstantiate<T5>();
|
var service5 = Get<T5>();
|
||||||
var service6 = GetOrRegisterInstantiate<T6>();
|
var service6 = Get<T6>();
|
||||||
var service7 = GetOrRegisterInstantiate<T7>();
|
var service7 = Get<T7>();
|
||||||
action(service1, service2, service3, service4, service5, service6, service7);
|
action(service1, service2, service3, service4, service5, service6, service7);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run<T1, T2, T3, T4, T5, T6, T7, T8>(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
|
public void Run<T1, T2, T3, T4, T5, T6, T7, T8>(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
|
||||||
{
|
{
|
||||||
var service1 = GetOrRegisterInstantiate<T1>();
|
var service1 = Get<T1>();
|
||||||
var service2 = GetOrRegisterInstantiate<T2>();
|
var service2 = Get<T2>();
|
||||||
var service3 = GetOrRegisterInstantiate<T3>();
|
var service3 = Get<T3>();
|
||||||
var service4 = GetOrRegisterInstantiate<T4>();
|
var service4 = Get<T4>();
|
||||||
var service5 = GetOrRegisterInstantiate<T5>();
|
var service5 = Get<T5>();
|
||||||
var service6 = GetOrRegisterInstantiate<T6>();
|
var service6 = Get<T6>();
|
||||||
var service7 = GetOrRegisterInstantiate<T7>();
|
var service7 = Get<T7>();
|
||||||
var service8 = GetOrRegisterInstantiate<T8>();
|
var service8 = Get<T8>();
|
||||||
action(service1, service2, service3, service4, service5, service6, service7, service8);
|
action(service1, service2, service3, service4, service5, service6, service7, service8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ namespace Serein.Library.Web
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Router : IRouter
|
public class Router : IRouter
|
||||||
{
|
{
|
||||||
|
private readonly ISereinIOC SereinIOC; // 用于存储路由信息
|
||||||
|
|
||||||
|
public Router(ISereinIOC SereinIOC)
|
||||||
|
{
|
||||||
|
this.SereinIOC = SereinIOC;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 控制器实例对象的类型,每次调用都会重新实例化,[Url - ControllerType]
|
/// 控制器实例对象的类型,每次调用都会重新实例化,[Url - ControllerType]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -39,8 +45,7 @@ namespace Serein.Library.Web
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, MethodInfo>> _routes;
|
private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, MethodInfo>> _routes;
|
||||||
|
|
||||||
[AutoInjection]
|
|
||||||
public ISereinIOC SereinIOC { get; set; } // 用于存储路由信息
|
|
||||||
// private readonly ILoggerService loggerService; // 用于存储路由信息
|
// private readonly ILoggerService loggerService; // 用于存储路由信息
|
||||||
|
|
||||||
//private Type PostRequest;
|
//private Type PostRequest;
|
||||||
|
|||||||
@@ -13,13 +13,18 @@ namespace Serein.Library.Web
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// HTTP接口监听类
|
/// HTTP接口监听类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[AutoRegister]
|
||||||
public class WebServer
|
public class WebServer
|
||||||
{
|
{
|
||||||
[AutoInjection]
|
private readonly IRouter Router;// 路由器
|
||||||
public IRouter Router { get; set; } // 路由器
|
public WebServer(IRouter router)
|
||||||
|
{
|
||||||
|
this.Router = router;
|
||||||
|
}
|
||||||
|
|
||||||
[AutoInjection]
|
|
||||||
public NodeRunCts nodeRunCts { get; set; }
|
//[AutoInjection]
|
||||||
|
//public NodeRunCts nodeRunCts { get; set; }
|
||||||
|
|
||||||
private HttpListener listener; // HTTP 监听器
|
private HttpListener listener; // HTTP 监听器
|
||||||
private RequestLimiter requestLimiter; //接口防刷
|
private RequestLimiter requestLimiter; //接口防刷
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Net461DllTest.Enums;
|
using Net461DllTest.Enums;
|
||||||
using Net461DllTest.Signal;
|
using Net461DllTest.Signal;
|
||||||
using Net461DllTest.Utils;
|
using Net461DllTest.Utils;
|
||||||
|
using Serein.Library.Attributes;
|
||||||
using Serein.Library.NodeFlow.Tool;
|
using Serein.Library.NodeFlow.Tool;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ namespace Net461DllTest.Device
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 官方文档:如果没有主动Open,则会每次读写操作的时候自动打开自动和关闭连接,这样会使读写效率大大减低。所以建议手动Open和Close。
|
/// 官方文档:如果没有主动Open,则会每次读写操作的时候自动打开自动和关闭连接,这样会使读写效率大大减低。所以建议手动Open和Close。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[AutoRegister]
|
||||||
public class SiemensPlcDevice : ChannelFlowTrigger<OrderSignal>
|
public class SiemensPlcDevice : ChannelFlowTrigger<OrderSignal>
|
||||||
{
|
{
|
||||||
public SiemensClient Client { get; set; }
|
public SiemensClient Client { get; set; }
|
||||||
|
|||||||
@@ -21,23 +21,18 @@ namespace Net461DllTest.LogicControl
|
|||||||
GetPparkingSpace,
|
GetPparkingSpace,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AutoRegister]
|
||||||
[DynamicFlow]
|
[DynamicFlow]
|
||||||
public class ParkingLogicControl
|
public class ParkingLogicControl
|
||||||
{
|
{
|
||||||
[AutoInjection]
|
private readonly PrakingDevice PrakingDevice;
|
||||||
public PrakingDevice PrakingDevice { get; set; }
|
|
||||||
|
|
||||||
|
public ParkingLogicControl(PrakingDevice PrakingDevice)
|
||||||
[NodeAction(NodeType.Init)]
|
|
||||||
public void Init(IDynamicContext context)
|
|
||||||
{
|
{
|
||||||
|
this.PrakingDevice = PrakingDevice;
|
||||||
context.Env.IOC.Register<PrakingDevice>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[NodeAction(NodeType.Flipflop, "等待车位调取命令",ReturnType=typeof(string))]
|
[NodeAction(NodeType.Flipflop, "等待车位调取命令",ReturnType=typeof(string))]
|
||||||
public async Task<IFlipflopContext> GetPparkingSpace(ParkingCommand parkingCommand = ParkingCommand.GetPparkingSpace)
|
public async Task<IFlipflopContext> GetPparkingSpace(ParkingCommand parkingCommand = ParkingCommand.GetPparkingSpace)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,21 +19,21 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Net461DllTest.LogicControl
|
namespace Net461DllTest.LogicControl
|
||||||
{
|
{
|
||||||
|
[AutoRegister]
|
||||||
[DynamicFlow]
|
[DynamicFlow]
|
||||||
public class PlcLogicControl
|
public class PlcLogicControl
|
||||||
{
|
{
|
||||||
[AutoInjection]
|
private readonly SiemensPlcDevice MyPlc;
|
||||||
public SiemensPlcDevice MyPlc { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public PlcLogicControl(SiemensPlcDevice MyPlc)
|
||||||
|
{
|
||||||
|
this.MyPlc = MyPlc;
|
||||||
|
}
|
||||||
|
|
||||||
#region 初始化、初始化完成以及退出的事件
|
#region 初始化、初始化完成以及退出的事件
|
||||||
[NodeAction(NodeType.Init)] // Init : 初始化事件,流程启动时执行
|
[NodeAction(NodeType.Init)] // Init : 初始化事件,流程启动时执行
|
||||||
public void Init(IDynamicContext context)
|
public void Init(IDynamicContext context)
|
||||||
{
|
{
|
||||||
context.Env.IOC.Register<SiemensPlcDevice>(); // 注册Plc设备
|
|
||||||
context.Env.IOC.Register<WebServer>(); // 注册Web服务
|
|
||||||
// // 注册控制器
|
// // 注册控制器
|
||||||
context.Env.IOC.Run<IRouter>(router => {
|
context.Env.IOC.Run<IRouter>(router => {
|
||||||
router.RegisterController(typeof(ApiController));
|
router.RegisterController(typeof(ApiController));
|
||||||
@@ -146,14 +146,14 @@ namespace Net461DllTest.LogicControl
|
|||||||
|
|
||||||
if (MyPlc.State == PlcState.Runing)
|
if (MyPlc.State == PlcState.Runing)
|
||||||
{
|
{
|
||||||
if (!varInfo.IsProtected)
|
if (varInfo.IsProtected)
|
||||||
{
|
{
|
||||||
MyPlc.Write(varInfo, value);
|
Console.WriteLine($"PLC变量{varInfo}当前禁止写入");
|
||||||
Console.WriteLine($"PLC变量{varInfo}写入数据:{value}");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine($"PLC变量{varInfo}当前禁止写入");
|
MyPlc.Write(varInfo, value);
|
||||||
|
Console.WriteLine($"PLC变量{varInfo}写入数据:{value}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Net461DllTest.Signal;
|
using Net461DllTest.Device;
|
||||||
|
using Net461DllTest.Signal;
|
||||||
using Net461DllTest.ViewModel;
|
using Net461DllTest.ViewModel;
|
||||||
using Serein.Library.Api;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Attributes;
|
using Serein.Library.Attributes;
|
||||||
@@ -11,7 +12,7 @@ using System.Windows.Forms;
|
|||||||
|
|
||||||
namespace Net461DllTest.LogicControl
|
namespace Net461DllTest.LogicControl
|
||||||
{
|
{
|
||||||
|
[AutoRegister]
|
||||||
public class ViewManagement
|
public class ViewManagement
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -46,8 +47,11 @@ namespace Net461DllTest.LogicControl
|
|||||||
[DynamicFlow]
|
[DynamicFlow]
|
||||||
public class ViewLogicControl
|
public class ViewLogicControl
|
||||||
{
|
{
|
||||||
[AutoInjection]
|
private readonly ViewManagement ViewManagement;
|
||||||
public ViewManagement ViewManagement { get; set; }
|
public ViewLogicControl(ViewManagement ViewManagement)
|
||||||
|
{
|
||||||
|
this.ViewManagement = ViewManagement;
|
||||||
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Init)]
|
[NodeAction(NodeType.Init)]
|
||||||
public void Init(IDynamicContext context)
|
public void Init(IDynamicContext context)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Net461DllTest.Device;
|
using Net461DllTest.Device;
|
||||||
using Net461DllTest.Signal;
|
using Net461DllTest.Signal;
|
||||||
using Net461DllTest.ViewModel;
|
using Net461DllTest.ViewModel;
|
||||||
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Attributes;
|
using Serein.Library.Attributes;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -16,11 +17,17 @@ namespace Net461DllTest
|
|||||||
{
|
{
|
||||||
public partial class FromWorkBenchView : Form
|
public partial class FromWorkBenchView : Form
|
||||||
{
|
{
|
||||||
[AutoInjection]
|
private FromWorkBenchViewModel ViewModel;
|
||||||
public FromWorkBenchViewModel ViewModel { get; set; }
|
|
||||||
public FromWorkBenchView()
|
public FromWorkBenchView(IFlowEnvironment env)
|
||||||
{
|
{
|
||||||
|
ViewModel = env.IOC.Instantiate<FromWorkBenchViewModel>();
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
listBox1.Items.Clear();
|
listBox1.Items.Clear();
|
||||||
var enumValues = Enum.GetValues(typeof(OrderSignal)).Cast<OrderSignal>();
|
var enumValues = Enum.GetValues(typeof(OrderSignal)).Cast<OrderSignal>();
|
||||||
foreach (var value in enumValues)
|
foreach (var value in enumValues)
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ namespace Net461DllTest.ViewModel
|
|||||||
{
|
{
|
||||||
public class FromWorkBenchViewModel
|
public class FromWorkBenchViewModel
|
||||||
{
|
{
|
||||||
[AutoInjection]
|
public FromWorkBenchViewModel(SiemensPlcDevice Device)
|
||||||
public SiemensPlcDevice Device { get; set; }
|
{
|
||||||
|
this.Device = Device;
|
||||||
|
}
|
||||||
|
private SiemensPlcDevice Device;
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
public string GetDeviceInfo()
|
public string GetDeviceInfo()
|
||||||
@@ -20,7 +24,6 @@ namespace Net461DllTest.ViewModel
|
|||||||
return Device?.ToString();
|
return Device?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Trigger(OrderSignal signal,string spcaeNumber)
|
public void Trigger(OrderSignal signal,string spcaeNumber)
|
||||||
{
|
{
|
||||||
_ = Task.Run(() =>
|
_ = Task.Run(() =>
|
||||||
|
|||||||
@@ -200,8 +200,12 @@ namespace Serein.NodeFlow.Base
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
MethodDetails md = MethodDetails;
|
MethodDetails md = MethodDetails;
|
||||||
var del = md.MethodDelegate.Clone();
|
//var del = md.MethodDelegate.Clone();
|
||||||
md.ActingInstance ??= context.Env.IOC.GetOrRegisterInstantiate(MethodDetails.ActingInstanceType);
|
if (!context.Env.TryGetDelegate(md.MethodName, out var del))
|
||||||
|
{
|
||||||
|
throw new Exception("不存在对应委托");
|
||||||
|
}
|
||||||
|
md.ActingInstance ??= context.Env.IOC.Get(MethodDetails.ActingInstanceType);
|
||||||
object instance = md.ActingInstance;
|
object instance = md.ActingInstance;
|
||||||
|
|
||||||
var haveParameter = md.ExplicitDatas.Length > 0;
|
var haveParameter = md.ExplicitDatas.Length > 0;
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 运行环境
|
/// 运行环境
|
||||||
@@ -47,12 +46,12 @@ namespace Serein.NodeFlow
|
|||||||
public FlowEnvironment()
|
public FlowEnvironment()
|
||||||
{
|
{
|
||||||
sereinIOC = new SereinIOC();
|
sereinIOC = new SereinIOC();
|
||||||
ChannelFlowInterrupt = new ChannelFlowInterrupt();
|
//ChannelFlowInterrupt = new ChannelFlowInterrupt();
|
||||||
LoadedAssemblyPaths = new List<string>();
|
//LoadedAssemblyPaths = new List<string>();
|
||||||
LoadedAssemblies = new List<Assembly>();
|
//LoadedAssemblies = new List<Assembly>();
|
||||||
MethodDetailss = new List<MethodDetails>();
|
//MethodDetailss = new List<MethodDetails>();
|
||||||
Nodes = new Dictionary<string, NodeModelBase>();
|
//Nodes = new Dictionary<string, NodeModelBase>();
|
||||||
FlipflopNodes = new List<SingleFlipflopNode>();
|
//FlipflopNodes = new List<SingleFlipflopNode>();
|
||||||
IsGlobalInterrupt = false;
|
IsGlobalInterrupt = false;
|
||||||
flowStarter = null;
|
flowStarter = null;
|
||||||
|
|
||||||
@@ -70,7 +69,12 @@ namespace Serein.NodeFlow
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载Dll
|
/// 加载Dll
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event LoadDLLHandler OnDllLoad;
|
public event LoadDllHandler OnDllLoad;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除DLL
|
||||||
|
/// </summary>
|
||||||
|
public event RemoteDllHandler OnDllRemote;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 项目加载完成
|
/// 项目加载完成
|
||||||
@@ -158,27 +162,36 @@ namespace Serein.NodeFlow
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 存储加载的程序集路径
|
/// 存储加载的程序集路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<string> LoadedAssemblyPaths { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 存储加载的程序集
|
/// 存储加载的程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<Assembly> LoadedAssemblies { get; }
|
private List<NodeLibrary> NodeLibrarys { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 存储所有方法信息
|
/// 存储所有方法信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<MethodDetails> MethodDetailss { get; }
|
//private MethodDetailss { get; } = [];
|
||||||
|
private Dictionary<NodeLibrary, List<MethodDetails>> MethodDetailss { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 环境加载的节点集合
|
/// 环境加载的节点集合
|
||||||
|
/// Node Guid - Node Model
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Dictionary<string, NodeModelBase> Nodes { get; }
|
private Dictionary<string, NodeModelBase> Nodes { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 存放触发器节点(运行时全部调用)
|
/// 存放触发器节点(运行时全部调用)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<SingleFlipflopNode> FlipflopNodes { get; }
|
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
||||||
|
private List<Type> AutoRegisterTypes { get; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存放委托
|
||||||
|
///
|
||||||
|
/// md.Methodname - delegate
|
||||||
|
/// </summary>
|
||||||
|
private ConcurrentDictionary<string, Delegate> MethodDelegates { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 起始节点私有属性
|
/// 起始节点私有属性
|
||||||
@@ -225,14 +238,25 @@ namespace Serein.NodeFlow
|
|||||||
flowStarter = new FlowStarter();
|
flowStarter = new FlowStarter();
|
||||||
var nodes = Nodes.Values.ToList();
|
var nodes = Nodes.Values.ToList();
|
||||||
|
|
||||||
List<MethodDetails> initMethods;
|
List<MethodDetails> initMethods = [];
|
||||||
List<MethodDetails> loadingMethods;
|
List<MethodDetails> loadMethods = [];
|
||||||
List<MethodDetails> exitMethods;
|
List<MethodDetails> exitMethods = [];
|
||||||
initMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Init).ToList();
|
foreach(var mds in MethodDetailss.Values)
|
||||||
loadingMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Loading).ToList();
|
{
|
||||||
exitMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Exit).ToList();
|
var initMds = mds.Where(it => it.MethodDynamicType == NodeType.Init);
|
||||||
|
var loadMds = mds.Where(it => it.MethodDynamicType == NodeType.Loading);
|
||||||
await flowStarter.RunAsync(this, nodes, initMethods, loadingMethods, exitMethods);
|
var exitMds = mds.Where(it => it.MethodDynamicType == NodeType.Exit);
|
||||||
|
initMethods.AddRange(initMds);
|
||||||
|
loadMethods.AddRange(loadMds);
|
||||||
|
exitMethods.AddRange(exitMds);
|
||||||
|
}
|
||||||
|
this.IOC.Reset(); // 开始运行时清空ioc中注册的实例
|
||||||
|
this.IOC.CustomRegisterInstance(typeof(IFlowEnvironment).FullName,this);
|
||||||
|
foreach (var type in AutoRegisterTypes)
|
||||||
|
{
|
||||||
|
this.IOC.Register(type);
|
||||||
|
}
|
||||||
|
await flowStarter.RunAsync(this, nodes, initMethods, loadMethods, exitMethods);
|
||||||
|
|
||||||
if (flowStarter?.FlipFlopState == RunState.NoStart)
|
if (flowStarter?.FlipFlopState == RunState.NoStart)
|
||||||
{
|
{
|
||||||
@@ -289,8 +313,8 @@ namespace Serein.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void ClearAll()
|
public void ClearAll()
|
||||||
{
|
{
|
||||||
LoadedAssemblyPaths.Clear();
|
//LoadedAssemblyPaths.Clear();
|
||||||
LoadedAssemblies.Clear();
|
NodeLibrarys.Clear();
|
||||||
MethodDetailss.Clear();
|
MethodDetailss.Clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -311,12 +335,7 @@ namespace Serein.NodeFlow
|
|||||||
foreach (var dll in dllPaths)
|
foreach (var dll in dllPaths)
|
||||||
{
|
{
|
||||||
var dllFilePath = System.IO.Path.GetFullPath(System.IO.Path.Combine(filePath, dll));
|
var dllFilePath = System.IO.Path.GetFullPath(System.IO.Path.Combine(filePath, dll));
|
||||||
(var assembly, var registerTypes, var mdlist) = LoadAssembly(dllFilePath);
|
LoadDllNodeInfo(dllFilePath);
|
||||||
if (assembly is not null && mdlist.Count > 0)
|
|
||||||
{
|
|
||||||
MethodDetailss.AddRange(mdlist); // 暂存方法描述
|
|
||||||
OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, mdlist)); // 通知UI创建dll面板显示
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 方法加载完成,缓存到运行环境中。
|
// 方法加载完成,缓存到运行环境中。
|
||||||
//MethodDetailss.AddRange(methodDetailss);
|
//MethodDetailss.AddRange(methodDetailss);
|
||||||
@@ -434,8 +453,7 @@ namespace Serein.NodeFlow
|
|||||||
SetStartNode(project.StartNode);
|
SetStartNode(project.StartNode);
|
||||||
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs());
|
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存项目为项目文件
|
/// 保存项目为项目文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -444,7 +462,7 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
var projectData = new SereinProjectData()
|
var projectData = new SereinProjectData()
|
||||||
{
|
{
|
||||||
Librarys = LoadedAssemblies.Select(assemblies => assemblies.ToLibrary()).ToArray(),
|
Librarys = NodeLibrarys.Select(assemblies => assemblies.Assembly.ToLibrary()).ToArray(),
|
||||||
Nodes = Nodes.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
Nodes = Nodes.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
||||||
StartNode = Nodes.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
StartNode = Nodes.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
||||||
};
|
};
|
||||||
@@ -458,14 +476,45 @@ namespace Serein.NodeFlow
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void LoadDll(string dllPath)
|
public void LoadDll(string dllPath)
|
||||||
{
|
{
|
||||||
(var assembly, _, var list) = LoadAssembly(dllPath);
|
LoadDllNodeInfo(dllPath);
|
||||||
if (assembly is not null && list.Count > 0)
|
}
|
||||||
|
|
||||||
|
public bool RemoteDll(string assemblyFullName)
|
||||||
|
{
|
||||||
|
var library = NodeLibrarys.FirstOrDefault(nl => nl.Assembly.FullName.Equals(assemblyFullName));
|
||||||
|
if(library is null)
|
||||||
{
|
{
|
||||||
MethodDetailss.AddRange(list);
|
return false;
|
||||||
OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list));
|
}
|
||||||
|
|
||||||
|
var nodes = Nodes.Values.ToDictionary(
|
||||||
|
key => key.MethodDetails.MethodName,
|
||||||
|
value => value
|
||||||
|
);
|
||||||
|
if(nodes.Count == 0)
|
||||||
|
{
|
||||||
|
return true; // 当前无节点,可以直接删除
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MethodDetailss.TryGetValue(library,out var mds)) // 存在方法
|
||||||
|
{
|
||||||
|
foreach(var md in mds)
|
||||||
|
{
|
||||||
|
if (nodes.ContainsKey(md.MethodName))
|
||||||
|
{
|
||||||
|
return false; // 创建过相关的节点
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MethodDetailss.Remove(library);
|
||||||
|
return true; // 没有创建相关的节点
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 运行时创建节点
|
/// 运行时创建节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -503,10 +552,10 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
var remoteNode = GuidToModel(nodeGuid);
|
var remoteNode = GuidToModel(nodeGuid);
|
||||||
if (remoteNode is null) return;
|
if (remoteNode is null) return;
|
||||||
if (remoteNode.IsStart)
|
//if (remoteNode.IsStart)
|
||||||
{
|
//{
|
||||||
return;
|
// return;
|
||||||
}
|
//}
|
||||||
if (remoteNode is SingleFlipflopNode flipflopNode)
|
if (remoteNode is SingleFlipflopNode flipflopNode)
|
||||||
{
|
{
|
||||||
flowStarter?.TerminateGlobalFlipflopRuning(flipflopNode); // 假设被移除的是全局触发器,尝试从启动器移除
|
flowStarter?.TerminateGlobalFlipflopRuning(flipflopNode); // 假设被移除的是全局触发器,尝试从启动器移除
|
||||||
@@ -618,8 +667,16 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(name))
|
if (!string.IsNullOrEmpty(name))
|
||||||
{
|
{
|
||||||
md = MethodDetailss.FirstOrDefault(it => it.MethodName == name);
|
foreach(var mds in MethodDetailss.Values)
|
||||||
return md != null;
|
{
|
||||||
|
md = mds.FirstOrDefault(it => it.MethodName == name);
|
||||||
|
if(md != null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
md = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -628,6 +685,19 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetDelegate(string methodName, out Delegate del)
|
||||||
|
{
|
||||||
|
if (MethodDelegates.TryGetValue(methodName, out del))
|
||||||
|
{
|
||||||
|
return del != null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
del = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置起点控件
|
/// 设置起点控件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -850,7 +920,23 @@ namespace Serein.NodeFlow
|
|||||||
/// 加载指定路径的DLL文件
|
/// 加载指定路径的DLL文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dllPath"></param>
|
/// <param name="dllPath"></param>
|
||||||
private (Assembly?, List<Type> ,List<MethodDetails>) LoadAssembly(string dllPath)
|
|
||||||
|
private void LoadDllNodeInfo(string dllPath)
|
||||||
|
{
|
||||||
|
(var nodeLibrary, var registerTypes, var mdlist) = LoadAssembly(dllPath);
|
||||||
|
if (nodeLibrary is not null && mdlist.Count > 0)
|
||||||
|
{
|
||||||
|
MethodDetailss.Add(nodeLibrary, mdlist);
|
||||||
|
NodeLibrarys.Add(nodeLibrary);
|
||||||
|
AutoRegisterTypes.AddRange(registerTypes);
|
||||||
|
|
||||||
|
OnDllLoad?.Invoke(new LoadDllEventArgs(nodeLibrary, mdlist)); // 通知UI创建dll面板显示
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private (NodeLibrary?, List<Type> ,List<MethodDetails>) LoadAssembly(string dllPath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -867,22 +953,36 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
List<MethodDetails> methodDetails = new List<MethodDetails>();
|
List<MethodDetails> methodDetails = new List<MethodDetails>();
|
||||||
// 遍历扫描的类型
|
// 遍历扫描的类型
|
||||||
foreach (var item in scanTypes)
|
foreach (var type in scanTypes)
|
||||||
{
|
{
|
||||||
// 加载DLL,创建 MethodDetails、实例作用对象、委托方法
|
// 加载DLL,创建 MethodDetails、实例作用对象、委托方法
|
||||||
var itemMethodDetails = MethodDetailsHelperTmp.GetList(item);
|
var assemblyName = type.Assembly.GetName().Name;
|
||||||
methodDetails.AddRange(itemMethodDetails);
|
var methods = MethodDetailsHelperTmp.GetMethodsToProcess(type);
|
||||||
//foreach (var md in itemMethodDetails)
|
foreach(var method in methods)
|
||||||
//{
|
{
|
||||||
// // var instanceType =
|
(var md, var del) = MethodDetailsHelperTmp.CreateMethodDetails(type, method, assemblyName);
|
||||||
// // Activator.CreateInstance(md.ActingInstanceType);
|
|
||||||
// // SereinIoc.RegisterInstantiate(md.ActingInstance);
|
if (MethodDelegates.TryAdd(md.MethodName, del))
|
||||||
// SereinIoc.Register(md.ActingInstanceType);
|
{
|
||||||
//}
|
methodDetails.Add(md);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"节点委托创建失败:{md.MethodName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//methodDetails.AddRange(itemMethodDetails);
|
||||||
}
|
}
|
||||||
LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中
|
|
||||||
LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径
|
var nodeLibrary = new NodeLibrary
|
||||||
return (assembly, autoRegisterTypes , methodDetails);
|
{
|
||||||
|
Assembly = assembly,
|
||||||
|
Path = dllPath,
|
||||||
|
};
|
||||||
|
//LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中
|
||||||
|
//LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径
|
||||||
|
return (nodeLibrary, autoRegisterTypes , methodDetails);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1068,8 +1168,6 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region IOC容器相关
|
#region IOC容器相关
|
||||||
ISereinIOC ISereinIOC.Reset()
|
ISereinIOC ISereinIOC.Reset()
|
||||||
{
|
{
|
||||||
@@ -1095,38 +1193,45 @@ namespace Serein.NodeFlow
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
T ISereinIOC.GetOrRegisterInstantiate<T>()
|
//T ISereinIOC.GetOrRegisterInstantiate<T>()
|
||||||
{
|
//{
|
||||||
return sereinIOC.GetOrRegisterInstantiate<T>();
|
// return sereinIOC.GetOrRegisterInstantiate<T>();
|
||||||
|
|
||||||
}
|
//}
|
||||||
|
|
||||||
object ISereinIOC.GetOrRegisterInstantiate(Type type)
|
//object ISereinIOC.GetOrRegisterInstantiate(Type type)
|
||||||
{
|
//{
|
||||||
return sereinIOC.GetOrRegisterInstantiate(type);
|
// return sereinIOC.GetOrRegisterInstantiate(type);
|
||||||
}
|
//}
|
||||||
|
|
||||||
object ISereinIOC.Get(Type type)
|
object ISereinIOC.Get(Type type)
|
||||||
{
|
{
|
||||||
return sereinIOC.Get(type);
|
return sereinIOC.Get(type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
T ISereinIOC.Get<T>()
|
||||||
|
{
|
||||||
|
return (T)sereinIOC.Get(typeof(T));
|
||||||
|
}
|
||||||
T ISereinIOC.Get<T>(string key)
|
T ISereinIOC.Get<T>(string key)
|
||||||
{
|
{
|
||||||
return sereinIOC.Get<T>(key);
|
return sereinIOC.Get<T>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ISereinIOC.CustomRegisterInstance(string key, object instance, bool needInjectProperty)
|
void ISereinIOC.CustomRegisterInstance(string key, object instance, bool needInjectProperty)
|
||||||
{
|
{
|
||||||
sereinIOC.CustomRegisterInstance(key, instance, needInjectProperty);
|
sereinIOC.CustomRegisterInstance(key, instance, needInjectProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
object ISereinIOC.Instantiate(Type type, params object[] parameters)
|
object ISereinIOC.Instantiate(Type type)
|
||||||
{
|
{
|
||||||
return sereinIOC.Instantiate(type, parameters);
|
return sereinIOC.Instantiate(type);
|
||||||
|
}
|
||||||
|
T ISereinIOC.Instantiate<T>()
|
||||||
|
{
|
||||||
|
return sereinIOC.Instantiate<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ISereinIOC ISereinIOC.Build()
|
ISereinIOC ISereinIOC.Build()
|
||||||
{
|
{
|
||||||
sereinIOC.Build();
|
sereinIOC.Build();
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
nodeMd.ActingInstance = null;
|
nodeMd.ActingInstance = null;
|
||||||
}
|
}
|
||||||
env.IOC.Reset(); // 开始运行时清空ioc中注册的实例
|
|
||||||
env.IOC.CustomRegisterInstance(typeof(ISereinIOC).FullName, env);
|
env.IOC.CustomRegisterInstance(typeof(ISereinIOC).FullName, env);
|
||||||
// 初始化ioc容器中的类型对象
|
// 初始化ioc容器中的类型对象
|
||||||
foreach (var md in thisRuningMds)
|
foreach (var md in thisRuningMds)
|
||||||
@@ -178,12 +178,11 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
CheckStartState(); // 初始化IOC后检查状态
|
CheckStartState(); // 初始化IOC后检查状态
|
||||||
|
|
||||||
|
|
||||||
env.IOC.Build(); // 流程启动前的初始化
|
env.IOC.Build(); // 流程启动前的初始化
|
||||||
|
|
||||||
foreach (var md in thisRuningMds)
|
foreach (var md in thisRuningMds)
|
||||||
{
|
{
|
||||||
md.ActingInstance = env.IOC.GetOrRegisterInstantiate(md.ActingInstanceType);
|
md.ActingInstance = env.IOC.Get(md.ActingInstanceType);
|
||||||
if(md.ActingInstance is null)
|
if(md.ActingInstance is null)
|
||||||
{
|
{
|
||||||
await Console.Out.WriteLineAsync($"{md.MethodName} - 无法获取类型[{md.ActingInstanceType}]的实例");
|
await Console.Out.WriteLineAsync($"{md.MethodName} - 无法获取类型[{md.ActingInstanceType}]的实例");
|
||||||
@@ -215,14 +214,22 @@ namespace Serein.NodeFlow
|
|||||||
//object?[]? args = [Context];
|
//object?[]? args = [Context];
|
||||||
foreach (var md in initMethods) // 初始化
|
foreach (var md in initMethods) // 初始化
|
||||||
{
|
{
|
||||||
((Action<object, object?[]?>)md.MethodDelegate).Invoke(md.ActingInstance, [Context]);
|
if (!env.TryGetDelegate(md.MethodName, out var del))
|
||||||
|
{
|
||||||
|
throw new Exception("不存在对应委托");
|
||||||
|
}
|
||||||
|
((Action<object, object?[]?>)del).Invoke(md.ActingInstance, [Context]);
|
||||||
}
|
}
|
||||||
Context.Env.IOC.Build(); // 绑定初始化时注册的类型
|
Context.Env.IOC.Build(); // 绑定初始化时注册的类型
|
||||||
foreach (var md in loadingMethods) // 加载
|
foreach (var md in loadingMethods) // 加载
|
||||||
{
|
{
|
||||||
//object?[]? data = [md.ActingInstance, args];
|
//object?[]? data = [md.ActingInstance, args];
|
||||||
//md.MethodDelegate.DynamicInvoke(data);
|
//md.MethodDelegate.DynamicInvoke(data);
|
||||||
((Action<object, object?[]?>)md.MethodDelegate).Invoke(md.ActingInstance, [Context]);
|
if (!env.TryGetDelegate(md.MethodName, out var del))
|
||||||
|
{
|
||||||
|
throw new Exception("不存在对应委托");
|
||||||
|
}
|
||||||
|
((Action<object, object?[]?>)del).Invoke(md.ActingInstance, [Context]);
|
||||||
}
|
}
|
||||||
Context.Env.IOC.Build(); // 预防有人在加载时才注册类型,再绑定一次
|
Context.Env.IOC.Build(); // 预防有人在加载时才注册类型,再绑定一次
|
||||||
#endregion
|
#endregion
|
||||||
@@ -236,7 +243,11 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
foreach (MethodDetails? md in exitMethods)
|
foreach (MethodDetails? md in exitMethods)
|
||||||
{
|
{
|
||||||
((Action<object, object?[]?>)md.MethodDelegate).Invoke(md.ActingInstance, [Context]);
|
if (!env.TryGetDelegate(md.MethodName, out var del))
|
||||||
|
{
|
||||||
|
throw new Exception("不存在对应委托");
|
||||||
|
}
|
||||||
|
((Action<object, object?[]?>)del).Invoke(md.ActingInstance, [Context]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminateAllGlobalFlipflop();
|
TerminateAllGlobalFlipflop();
|
||||||
@@ -303,7 +314,7 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
if (dictGlobalFlipflop.TryAdd(singleFlipFlopNode, new CancellationTokenSource()))
|
if (dictGlobalFlipflop.TryAdd(singleFlipFlopNode, new CancellationTokenSource()))
|
||||||
{
|
{
|
||||||
singleFlipFlopNode.MethodDetails.ActingInstance ??= env.IOC.GetOrRegisterInstantiate(singleFlipFlopNode.MethodDetails.ActingInstanceType);
|
singleFlipFlopNode.MethodDetails.ActingInstance ??= env.IOC.Get(singleFlipFlopNode.MethodDetails.ActingInstanceType);
|
||||||
await FlipflopExecuteAsync(env, singleFlipFlopNode, dictGlobalFlipflop[singleFlipFlopNode]);
|
await FlipflopExecuteAsync(env, singleFlipFlopNode, dictGlobalFlipflop[singleFlipFlopNode]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ namespace Serein.NodeFlow.Model
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
MethodDetails md = MethodDetails;
|
MethodDetails md = MethodDetails;
|
||||||
var del = md.MethodDelegate.Clone();
|
if (!context.Env.TryGetDelegate(md.MethodName, out var del))
|
||||||
|
{
|
||||||
|
throw new Exception("不存在对应委托");
|
||||||
|
}
|
||||||
object instance = md.ActingInstance;
|
object instance = md.ActingInstance;
|
||||||
// Task<IFlipflopContext>? flipflopTask = null;
|
// Task<IFlipflopContext>? flipflopTask = null;
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -11,31 +11,39 @@ namespace Serein.NodeFlow.Tool;
|
|||||||
|
|
||||||
public static class MethodDetailsHelperTmp
|
public static class MethodDetailsHelperTmp
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成方法信息
|
/// 生成方法信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="serviceContainer"></param>
|
/// <param name="serviceContainer"></param>
|
||||||
/// <param name="type"></param>
|
/// <param name="type"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static List<MethodDetails> GetList(Type type)
|
//public static List<MethodDetails> GetList(Type type)
|
||||||
{
|
//{
|
||||||
var methodDetailsDictionary = new List<MethodDetails>();
|
// var methodDetailsDictionary = new List<MethodDetails>();
|
||||||
var assemblyName = type.Assembly.GetName().Name;
|
// var delegateDictionary = new List<Delegate>();
|
||||||
var methods = GetMethodsToProcess(type);
|
// var assemblyName = type.Assembly.GetName().Name;
|
||||||
|
// var methods = GetMethodsToProcess(type);
|
||||||
|
|
||||||
foreach (var method in methods)
|
// foreach (var method in methods)
|
||||||
{
|
// {
|
||||||
|
|
||||||
var methodDetails = CreateMethodDetails(type, method, assemblyName);
|
// (var methodDetails,var methodDelegate) = CreateMethodDetails(type, method, assemblyName);
|
||||||
methodDetailsDictionary.Add(methodDetails);
|
|
||||||
}
|
// methodDetailsDictionary.Add(methodDetails);
|
||||||
|
// delegateDictionary.Add(methodDelegate);
|
||||||
|
// }
|
||||||
|
|
||||||
return methodDetailsDictionary.OrderBy(it => it.MethodName).ToList();
|
// var mds = methodDetailsDictionary.OrderBy(it => it.MethodName).ToList();
|
||||||
}
|
// var dels = delegateDictionary;
|
||||||
|
|
||||||
|
// return mds;
|
||||||
|
//}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取处理方法
|
/// 获取处理方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static IEnumerable<MethodInfo> GetMethodsToProcess(Type type)
|
public static IEnumerable<MethodInfo> GetMethodsToProcess(Type type)
|
||||||
{
|
{
|
||||||
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||||
.Where(m => m.GetCustomAttribute<NodeActionAttribute>()?.Scan == true);
|
.Where(m => m.GetCustomAttribute<NodeActionAttribute>()?.Scan == true);
|
||||||
@@ -44,17 +52,17 @@ public static class MethodDetailsHelperTmp
|
|||||||
/// 创建方法信息
|
/// 创建方法信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static MethodDetails CreateMethodDetails(Type type, MethodInfo method, string assemblyName)
|
public static (MethodDetails,Delegate) CreateMethodDetails(Type type, MethodInfo method, string assemblyName)
|
||||||
{
|
{
|
||||||
|
|
||||||
var methodName = method.Name;
|
var methodName = method.Name;
|
||||||
var attribute = method.GetCustomAttribute<NodeActionAttribute>();
|
var attribute = method.GetCustomAttribute<NodeActionAttribute>();
|
||||||
if(attribute is null)
|
if(attribute is null)
|
||||||
{
|
{
|
||||||
return null;
|
return (null, null);
|
||||||
}
|
}
|
||||||
var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters());
|
var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters());
|
||||||
// 生成委托
|
//// 生成委托
|
||||||
var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型
|
var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型
|
||||||
method, // 方法信息
|
method, // 方法信息
|
||||||
method.GetParameters(),// 方法参数
|
method.GetParameters(),// 方法参数
|
||||||
@@ -75,12 +83,11 @@ public static class MethodDetailsHelperTmp
|
|||||||
// object instance = Activator.CreateInstance(type);
|
// object instance = Activator.CreateInstance(type);
|
||||||
var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}";
|
var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}";
|
||||||
|
|
||||||
return new MethodDetails
|
var md = new MethodDetails
|
||||||
{
|
{
|
||||||
ActingInstanceType = type,
|
ActingInstanceType = type,
|
||||||
// ActingInstance = instance,
|
// ActingInstance = instance,
|
||||||
MethodName = dllTypeMethodName,
|
MethodName = dllTypeMethodName,
|
||||||
MethodDelegate = methodDelegate,
|
|
||||||
MethodDynamicType = attribute.MethodDynamicType,
|
MethodDynamicType = attribute.MethodDynamicType,
|
||||||
MethodLockName = attribute.LockName,
|
MethodLockName = attribute.LockName,
|
||||||
MethodTips = attribute.MethodTips,
|
MethodTips = attribute.MethodTips,
|
||||||
@@ -88,6 +95,8 @@ public static class MethodDetailsHelperTmp
|
|||||||
ReturnType = returnType,
|
ReturnType = returnType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return (md, methodDelegate);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -283,16 +283,13 @@ namespace Serein.WorkBench
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载了DLL文件,dll内容
|
/// 加载了DLL文件,dll内容
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void FlowEnvironment_DllLoadEvent(LoadDLLEventArgs eventArgs)
|
private void FlowEnvironment_DllLoadEvent(LoadDllEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
this.Dispatcher.Invoke(() => {
|
this.Dispatcher.Invoke(() => {
|
||||||
Assembly assembly = eventArgs.Assembly;
|
NodeLibrary nodeLibrary = eventArgs.NodeLibrary;
|
||||||
List<MethodDetails> methodDetailss = eventArgs.MethodDetailss;
|
List<MethodDetails> methodDetailss = eventArgs.MethodDetailss;
|
||||||
|
|
||||||
var dllControl = new DllControl
|
var dllControl = new DllControl(nodeLibrary);
|
||||||
{
|
|
||||||
Header = "DLL name : " + assembly.GetName().Name // 设置控件标题为程序集名称
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var methodDetails in methodDetailss)
|
foreach (var methodDetails in methodDetailss)
|
||||||
{
|
{
|
||||||
@@ -306,6 +303,21 @@ namespace Serein.WorkBench
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var menu = new ContextMenu();
|
||||||
|
menu.Items.Add(CreateMenuItem("卸载", (s,e) =>
|
||||||
|
{
|
||||||
|
if (this.FlowEnvironment.RemoteDll(nodeLibrary.Assembly.FullName))
|
||||||
|
{
|
||||||
|
DllStackPanel.Children.Remove(dllControl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("卸载失败");
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
dllControl.ContextMenu = menu;
|
||||||
|
|
||||||
DllStackPanel.Children.Add(dllControl); // 将控件添加到界面上显示
|
DllStackPanel.Children.Add(dllControl); // 将控件添加到界面上显示
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -775,26 +787,26 @@ namespace Serein.WorkBench
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="regionControl"></param>
|
/// <param name="regionControl"></param>
|
||||||
/// <param name="childNodes"></param>
|
/// <param name="childNodes"></param>
|
||||||
private void AddNodeControlInRegeionControl(NodeControlBase regionControl, NodeInfo[] childNodes)
|
//private void AddNodeControlInRegeionControl(NodeControlBase regionControl, NodeInfo[] childNodes)
|
||||||
{
|
//{
|
||||||
foreach (var childNode in childNodes)
|
// foreach (var childNode in childNodes)
|
||||||
{
|
// {
|
||||||
if (FlowEnvironment.TryGetMethodDetails(childNode.MethodName, out MethodDetails md))
|
// if (FlowEnvironment.TryGetMethodDetails(childNode.MethodName, out MethodDetails md))
|
||||||
{
|
// {
|
||||||
var childNodeControl = CreateNodeControlOfNodeInfo(childNode, md);
|
// var childNodeControl = CreateNodeControlOfNodeInfo(childNode, md);
|
||||||
if (childNodeControl is null)
|
// if (childNodeControl is null)
|
||||||
{
|
// {
|
||||||
Console.WriteLine($"无法为节点类型创建节点控件: {childNode.MethodName}\r\n");
|
// Console.WriteLine($"无法为节点类型创建节点控件: {childNode.MethodName}\r\n");
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (regionControl is ConditionRegionControl conditionRegion)
|
// if (regionControl is ConditionRegionControl conditionRegion)
|
||||||
{
|
// {
|
||||||
conditionRegion.AddCondition(childNodeControl);
|
// conditionRegion.AddCondition(childNodeControl);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using Serein.Library.Entity;
|
using Serein.Library.Api;
|
||||||
|
using Serein.Library.Entity;
|
||||||
using Serein.Library.Enums;
|
using Serein.Library.Enums;
|
||||||
using Serein.NodeFlow;
|
using Serein.NodeFlow;
|
||||||
|
using System.Reflection;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Automation;
|
using System.Windows.Automation;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
@@ -18,12 +20,20 @@ namespace Serein.WorkBench.Node.View
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class DllControl : UserControl
|
public partial class DllControl : UserControl
|
||||||
{
|
{
|
||||||
|
private readonly NodeLibrary nodeLibrary;
|
||||||
|
|
||||||
public DllControl()
|
public DllControl()
|
||||||
{
|
{
|
||||||
Header = "DLL文件"; // 设置初始值
|
Header = "DLL文件"; // 设置初始值
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
public DllControl(NodeLibrary nodeLibrary)
|
||||||
|
{
|
||||||
|
this.nodeLibrary = nodeLibrary;
|
||||||
|
Header = "DLL name : " + nodeLibrary.Assembly.GetName().Name;
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -39,10 +49,6 @@ namespace Serein.WorkBench.Node.View
|
|||||||
DependencyProperty.Register("Header", typeof(string), typeof(DllControl), new PropertyMetadata(string.Empty));
|
DependencyProperty.Register("Header", typeof(string), typeof(DllControl), new PropertyMetadata(string.Empty));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 向动作面板添加类型的文本块
|
/// 向动作面板添加类型的文本块
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user