IOC容器添加构造函数注入(DLL类中使用AutoRegisterAttribute特性标注的类,会在流程启动时自动注册),提高可读性。

This commit is contained in:
fengjiayi
2024-09-30 02:45:49 +08:00
parent 7a310ff1df
commit ccf539b90f
23 changed files with 615 additions and 280 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>
/// 节点类型 /// 节点类型

View 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; }
}
}

View File

@@ -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

View File

@@ -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);
} }

View File

@@ -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;

View File

@@ -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; //接口防刷

View File

@@ -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; }

View File

@@ -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)
{ {

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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(() =>

View File

@@ -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;

View File

@@ -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();

View File

@@ -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]);
} }
} }

View File

@@ -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

View File

@@ -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);
} }

View File

@@ -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

View File

@@ -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>