优化了运行环境与启动器的运行逻辑,以及IOC容器的注册/绑定/获取对象的机制

This commit is contained in:
fengjiayi
2024-09-16 21:38:34 +08:00
parent bcbf6cb992
commit e20855a076
13 changed files with 551 additions and 970 deletions

View File

@@ -10,7 +10,9 @@ using System.Diagnostics;
using System.Net.Mime;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Xml.Linq;
using static Serein.NodeFlow.FlowStarter;
namespace Serein.NodeFlow
{
@@ -47,19 +49,28 @@ namespace Serein.NodeFlow
/// </summary>
public event LoadDLLHandler OnDllLoad;
/// <summary>
/// 加载节点
/// 加载节点事件
/// </summary>
public event LoadNodeHandler OnLoadNode;
/// <summary>
/// 连接节点
/// 节点连接属性改变事件
/// </summary>
public event NodeConnectChangeHandler OnNodeConnectChange;
/// <summary>
/// 创建节点
/// 节点创建时间
/// </summary>
public event NodeCreateHandler OnNodeCreate;
/// <summary>
/// 移除节点事件
/// </summary>
public event NodeRemoteHandler OnNodeRemote;
/// <summary>
/// 起始节点变化事件
/// </summary>
public event StartNodeChangeHandler OnStartNodeChange;
/// <summary>
/// 流程运行完成时间
/// </summary>
public event FlowRunCompleteHandler OnFlowRunComplete;
private FlowStarter? nodeFlowStarter = null;
@@ -72,7 +83,7 @@ namespace Serein.NodeFlow
/// <summary>
/// 一种轻量的IOC容器
/// </summary>
public SereinIoc SereinIoc { get; } = new SereinIoc();
// public SereinIoc SereinIoc { get; } = new SereinIoc();
/// <summary>
/// 存储加载的程序集路径
@@ -92,15 +103,17 @@ namespace Serein.NodeFlow
public Dictionary<string, NodeModelBase> Nodes { get; } = [];
public List<NodeModelBase> Regions { get; } = [];
// public List<NodeModelBase> Regions { get; } = [];
/// <summary>
/// 存放触发器节点(运行时全部调用)
/// </summary>
public List<SingleFlipflopNode> FlipflopNodes { get; } = [];
private NodeModelBase? _startNode = null;
/// <summary>
/// 私有属性
/// </summary>
private NodeModelBase _startNode;
/// <summary>
/// 起始节点
/// </summary>
@@ -112,17 +125,12 @@ namespace Serein.NodeFlow
}
set
{
if (_startNode is null)
{
value.IsStart = true;
_startNode = value;
}
else
{
if (_startNode is not null)
{
_startNode.IsStart = false;
value.IsStart = true;
_startNode = value;
}
value.IsStart = true;
_startNode = value;
}
}
@@ -132,19 +140,32 @@ namespace Serein.NodeFlow
/// <returns></returns>
public async Task StartAsync()
{
nodeFlowStarter = new FlowStarter(SereinIoc);
var nodes = Nodes.Values.ToList();
var flipflopNodes = nodes.Where(it => it.MethodDetails?.MethodDynamicType == NodeType.Flipflop
&& it.IsStart == false)
.Select(it => it as SingleFlipflopNode)
.ToList();
nodeFlowStarter = new FlowStarter();
List<SingleFlipflopNode> flipflopNodes = Nodes.Values.Where(it => it.MethodDetails?.MethodDynamicType == NodeType.Flipflop && it.IsStart == false)
.Select(it => (SingleFlipflopNode)it)
.Where(node => node is SingleFlipflopNode flipflopNode && flipflopNode.NotExitPreviousNode())
.ToList();// 获取需要再运行开始之前启动的触发器节点
var runMethodDetailess = Nodes.Values.Select(item => item.MethodDetails).ToList(); // 获取环境中所有节点的方法信息
var initMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Init).ToList();
var loadingMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Loading).ToList();
var exitMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Exit).ToList();
await nodeFlowStarter.RunAsync(StartNode,
this,
runMethodDetailess,
initMethods,
loadingMethods,
exitMethods,
flipflopNodes);
await nodeFlowStarter.RunAsync(StartNode, this, MethodDetailss, flipflopNodes);
if(nodeFlowStarter?.FlipFlopState == RunState.NoStart)
{
this.Exit(); // 未运行触发器时,才会调用结束方法
}
nodeFlowStarter = null;
}
public void Exit()
{
nodeFlowStarter?.Exit();
nodeFlowStarter = null;
OnFlowRunComplete?.Invoke(new FlowEventArgs());
}
@@ -162,19 +183,6 @@ namespace Serein.NodeFlow
#region
/// <summary>
/// 获取方法描述
/// </summary>
public bool TryGetMethodDetails(string name, out MethodDetails? md)
{
md = MethodDetailss.FirstOrDefault(it => it.MethodName == name);
if (md == null)
{
return false;
}
return true;
}
/// <summary>
/// 加载项目文件
/// </summary>
@@ -247,27 +255,34 @@ namespace Serein.NodeFlow
}
/// <summary>
/// 连接节点
/// 保存项目为项目文件
/// </summary>
/// <param name="fromNode">起始节点</param>
/// <param name="toNode">目标节点</param>
/// <param name="connectionType">连接关系</param>
public void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
/// <returns></returns>
public SereinOutputFileData SaveProject()
{
// 获取起始节点与目标节点
if (!Nodes.TryGetValue(fromNodeGuid, out NodeModelBase? fromNode) || !Nodes.TryGetValue(toNodeGuid, out NodeModelBase? toNode))
var projectData = new SereinOutputFileData()
{
return;
}
if (fromNode is null || toNode is null)
Librarys = LoadedAssemblies.Select(assemblies => assemblies.ToLibrary()).ToArray(),
Nodes = Nodes.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
StartNode = Nodes.Values.FirstOrDefault(it => it.IsStart)?.Guid,
};
return projectData;
}
/// <summary>
/// 从文件路径中加载DLL
/// </summary>
/// <param name="dllPath"></param>
/// <returns></returns>
public void LoadDll(string dllPath)
{
(var assembly, var list) = LoadAssembly(dllPath);
if (assembly is not null && list.Count > 0)
{
return;
MethodDetailss.AddRange(list);
OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list));
}
// 开始连接
ConnectNode(fromNode, toNode, connectionType); // 外部调用连接方法
}
/// <summary>
/// 创建节点
/// </summary>
@@ -326,66 +341,6 @@ namespace Serein.NodeFlow
SetStartNode(nodeBase);
}
}
/// <summary>
/// 从文件路径中加载DLL
/// </summary>
/// <param name="dllPath"></param>
/// <returns></returns>
public void LoadDll(string dllPath)
{
(var assembly, var list) = LoadAssembly(dllPath);
if (assembly is not null && list.Count > 0)
{
MethodDetailss.AddRange(list);
OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list));
}
}
/// <summary>
/// 保存项目为项目文件
/// </summary>
/// <returns></returns>
public SereinOutputFileData SaveProject()
{
var projectData = new SereinOutputFileData()
{
Librarys = LoadedAssemblies.Select(assemblies => assemblies.ToLibrary()).ToArray(),
Nodes = Nodes.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
StartNode = Nodes.Values.FirstOrDefault(it => it.IsStart)?.Guid,
};
return projectData;
}
/// <summary>
/// 移除连接关系
/// </summary>
/// <param name="fromNodeGuid"></param>
/// <param name="toNodeGuid"></param>
/// <param name="connectionType"></param>
/// <exception cref="NotImplementedException"></exception>
public void RemoteConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
{
// 获取起始节点与目标节点
if (!Nodes.TryGetValue(fromNodeGuid, out NodeModelBase? fromNode) || !Nodes.TryGetValue(toNodeGuid, out NodeModelBase? toNode))
{
return;
}
if (fromNode is null || toNode is null)
{
return;
}
fromNode.SuccessorNodes[connectionType].Remove(toNode);
toNode.PreviousNodes[connectionType].Remove(fromNode);
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
toNodeGuid,
connectionType,
NodeConnectChangeEventArgs.ChangeTypeEnum.Remote));
}
/// <summary>
/// 移除节点
/// </summary>
@@ -418,7 +373,7 @@ namespace Serein.NodeFlow
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(pNode.Guid,
remoteNode.Guid,
pCType,
NodeConnectChangeEventArgs.ChangeTypeEnum.Remote)); // 通知UI
NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI
}
}
@@ -433,7 +388,7 @@ namespace Serein.NodeFlow
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(remoteNode.Guid,
sNode.Guid,
sCType,
NodeConnectChangeEventArgs.ChangeTypeEnum.Remote)); // 通知UI
NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI
}
}
@@ -443,6 +398,68 @@ namespace Serein.NodeFlow
OnNodeRemote?.Invoke(new NodeRemoteEventArgs(nodeGuid));
}
/// <summary>
/// 连接节点
/// </summary>
/// <param name="fromNode">起始节点</param>
/// <param name="toNode">目标节点</param>
/// <param name="connectionType">连接关系</param>
public void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
{
// 获取起始节点与目标节点
if (!Nodes.TryGetValue(fromNodeGuid, out NodeModelBase? fromNode) || !Nodes.TryGetValue(toNodeGuid, out NodeModelBase? toNode))
{
return;
}
if (fromNode is null || toNode is null)
{
return;
}
// 开始连接
ConnectNode(fromNode, toNode, connectionType); // 外部调用连接方法
}
/// <summary>
/// 移除连接关系
/// </summary>
/// <param name="fromNodeGuid"></param>
/// <param name="toNodeGuid"></param>
/// <param name="connectionType"></param>
/// <exception cref="NotImplementedException"></exception>
public void RemoteConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
{
// 获取起始节点与目标节点
if (!Nodes.TryGetValue(fromNodeGuid, out NodeModelBase? fromNode) || !Nodes.TryGetValue(toNodeGuid, out NodeModelBase? toNode))
{
return;
}
if (fromNode is null || toNode is null)
{
return;
}
fromNode.SuccessorNodes[connectionType].Remove(toNode);
toNode.PreviousNodes[connectionType].Remove(fromNode);
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
toNodeGuid,
connectionType,
NodeConnectChangeEventArgs.ConnectChangeType.Remote));
}
/// <summary>
/// 获取方法描述
/// </summary>
public bool TryGetMethodDetails(string name, out MethodDetails? md)
{
md = MethodDetailss.FirstOrDefault(it => it.MethodName == name);
if (md == null)
{
return false;
}
return true;
}
/// <summary>
/// 设置起点控件
/// </summary>
@@ -494,14 +511,14 @@ namespace Serein.NodeFlow
{
// 加载DLL创建 MethodDetails、实例作用对象、委托方法
var itemMethodDetails = MethodDetailsHelperTmp.GetList(item, false);
foreach (var md in itemMethodDetails)
{
// var instanceType =
// Activator.CreateInstance(md.ActingInstanceType);
// SereinIoc.RegisterInstantiate(md.ActingInstance);
SereinIoc.Register(md.ActingInstanceType);
}
methodDetails.AddRange(itemMethodDetails);
//foreach (var md in itemMethodDetails)
//{
// // var instanceType =
// // Activator.CreateInstance(md.ActingInstanceType);
// // SereinIoc.RegisterInstantiate(md.ActingInstance);
// SereinIoc.Register(md.ActingInstanceType);
//}
}
LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中
LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径
@@ -514,7 +531,6 @@ namespace Serein.NodeFlow
}
}
/// <summary>
/// 连接节点
/// </summary>
@@ -573,7 +589,7 @@ namespace Serein.NodeFlow
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNode.Guid,
toNode.Guid,
connectionType,
NodeConnectChangeEventArgs.ChangeTypeEnum.Create)); // 通知UI
NodeConnectChangeEventArgs.ConnectChangeType.Create)); // 通知UI
}
/// <summary>
@@ -589,20 +605,11 @@ namespace Serein.NodeFlow
}
#endregion
#region
#region WPF
#region
#endregion
#region Socket的方式进行操作
#endregion
#endregion
}
}
public static class FlowFunc
{
public static Library.Entity.Library ToLibrary(this Assembly assembly)
@@ -625,6 +632,22 @@ namespace Serein.NodeFlow
_ => throw new NotImplementedException("未定义的流程状态")
};
}
public static bool NotExitPreviousNode(this SingleFlipflopNode node)
{
ConnectionType[] ct = [ConnectionType.IsSucceed,
ConnectionType.IsFail,
ConnectionType.IsError,
ConnectionType.Upstream];
foreach (ConnectionType ctType in ct)
{
if(node.PreviousNodes[ctType].Count > 0)
{
return false;
}
}
return true;
}
}

View File

@@ -16,69 +16,135 @@ namespace Serein.NodeFlow
/// <param name="methodDetails"></param>
public class FlowStarter
{
public FlowStarter(ISereinIoc serviceContainer/*, List<MethodDetails> methodDetails*/)
public FlowStarter()
{
SereinIoc = serviceContainer;
SereinIOC = new SereinIOC();
}
/// <summary>
/// 流程运行状态
/// </summary>
public enum RunState
{
/// <summary>
/// 等待开始
/// </summary>
NoStart,
/// <summary>
/// 正在运行
/// </summary>
Running,
/// <summary>
/// 运行完成
/// </summary>
Completion,
}
/// <summary>
/// 控制触发器的结束
/// </summary>
private NodeRunCts FlipFlopCts { get; set; } = null;
/// <summary>
/// 运行状态
/// </summary>
public RunState FlowState { get; private set; } = RunState.NoStart;
public RunState FlipFlopState { get; private set; } = RunState.NoStart;
/// <summary>
/// 运行时的IOC容器
/// </summary>
private ISereinIOC SereinIOC { get; } = null;
/// <summary>
/// 结束运行时需要执行的方法
/// </summary>
private Action ExitAction { get; set; } = null;
/// <summary>
/// 运行的上下文
/// </summary>
private IDynamicContext Context { get; set; } = null;
private ISereinIoc SereinIoc { get; }
// private List<MethodDetails> MethodDetailss { get; }
private Action ExitAction { get; set; } = null; //退出方法
private IDynamicContext Context { get; set; } = null; //上下文
public NodeRunCts MainCts { get; set; }
/// <summary>
/// 开始运行
/// </summary>
/// <param name="nodes"></param>
/// <param name="startNode">起始节点</param>
/// <param name="env">运行环境</param>
/// <param name="runMd">环境中已加载的所有节点方法</param>
/// <param name="flipflopNodes">触发器节点</param>
/// <returns></returns>
// public async Task RunAsync(List<NodeModelBase> nodes, IFlowEnvironment flowEnvironment)
public async Task RunAsync(NodeModelBase startNode, IFlowEnvironment flowEnvironment, List<MethodDetails> methodDetailss, List<SingleFlipflopNode> flipflopNodes)
public async Task RunAsync(NodeModelBase startNode,
IFlowEnvironment env,
List<MethodDetails> runMd,
List<MethodDetails> initMethods,
List<MethodDetails> loadingMethods,
List<MethodDetails> exitMethods,
List<SingleFlipflopNode> flipflopNodes)
{
// var startNode = nodes.FirstOrDefault(p => p.IsStart);
if (startNode == null) { return; }
FlowState = RunState.Running; // 开始运行
if (startNode == null) {
FlowState = RunState.Completion; // 不存在起点,退出流程
return;
}
// 判断使用哪一种流程上下文
var isNetFramework = true;
if (isNetFramework)
{
Context = new Serein.Library.Framework.NodeFlow.DynamicContext(SereinIoc, flowEnvironment);
Context = new Serein.Library.Framework.NodeFlow.DynamicContext(SereinIOC, env);
}
else
{
Context = new Serein.Library.Core.NodeFlow.DynamicContext(SereinIoc, flowEnvironment);
Context = new Serein.Library.Core.NodeFlow.DynamicContext(SereinIOC, env);
}
MainCts = SereinIoc.GetOrCreateServiceInstance<NodeRunCts>();
foreach (var md in methodDetailss)
#region Ioc容器
// 清除节点使用的对象
foreach (var nodeMd in runMd)
{
SereinIoc.Register(md.ActingInstanceType);
nodeMd.ActingInstance = null;
}
SereinIoc.Build();
foreach (var md in flipflopNodes.Select(it => it.MethodDetails).ToArray())
SereinIOC.Reset(); // 开始运行时清空ioc中注册的实例
// 初始化ioc容器中的类型对象
foreach (var md in runMd)
{
md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType);
SereinIOC.Register(md.ActingInstanceType);
}
foreach (var md in methodDetailss)
SereinIOC.Build();
foreach (var md in runMd)
{
md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType);
md.ActingInstance = SereinIOC.GetOrInstantiate(md.ActingInstanceType);
}
var initMethods = methodDetailss.Where(it => it.MethodDynamicType == NodeType.Init).ToList();
var loadingMethods = methodDetailss.Where(it => it.MethodDynamicType == NodeType.Loading).ToList();
var exitMethods = methodDetailss.Where(it => it.MethodDynamicType == NodeType.Exit).ToList();
//foreach (var md in flipflopNodes.Select(it => it.MethodDetails).ToArray())
//{
// md.ActingInstance = SereinIoc.GetOrCreateServiceInstance(md.ActingInstanceType);
//}
#endregion
#region Node中初始化退
foreach (var md in initMethods) // 初始化
{
md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
}
foreach (var md in loadingMethods) // 加载
{
md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
}
foreach (var md in exitMethods) // 初始化
{
md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
}
object?[]? args = [Context];
ExitAction = () =>
{
//ServiceContainer.Run<WebServer>((web) =>
//{
// web?.Stop();
//});
foreach (MethodDetails? md in exitMethods)
{
md.ActingInstance = Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
object?[]? args = [Context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
@@ -86,53 +152,62 @@ namespace Serein.NodeFlow
{
Context.NodeRunCts.Cancel();
}
if (MainCts != null && !MainCts.IsCancellationRequested) MainCts.Cancel();
SereinIoc.Reset();
if (FlipFlopCts != null && !FlipFlopCts.IsCancellationRequested)
{
FlipFlopCts.Cancel();
}
FlowState = RunState.Completion;
FlipFlopState = RunState.Completion;
};
Context.SereinIoc.Build();
#endregion
#region IOC容器
foreach (var md in initMethods) // 初始化 - 调用方法
{
md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
object?[]? args = [Context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
Context.SereinIoc.Build();
foreach (var md in loadingMethods) // 加载
{
md.ActingInstance ??= Context.SereinIoc.GetOrInstantiate(md.ActingInstanceType);
object?[]? args = [Context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
}
#endregion
// 运行触发器节点
var singleFlipflopNodes = flipflopNodes.Select(it => (SingleFlipflopNode)it).ToArray();
// 使用 TaskCompletionSource 创建未启动的任务
var tasks = singleFlipflopNodes.Select(async node =>
{
await FlipflopExecute(node, flowEnvironment);
}).ToArray();
_ = Task.WhenAll(tasks);
// 节点任务的启动
try
{
await Task.Run(async () =>
if (flipflopNodes.Count > 0)
{
await startNode.StartExecution(Context);
//await Task.WhenAll([startNode.StartExecution(Context), .. tasks]);
});
FlipFlopState = RunState.Running;
// 如果存在需要启动的触发器,则开始启动
FlipFlopCts = SereinIOC.GetOrInstantiate<NodeRunCts>();
// 使用 TaskCompletionSource 创建未启动的触发器任务
var tasks = flipflopNodes.Select(async node =>
{
await FlipflopExecute(node, env);
}).ToArray();
_ = Task.WhenAll(tasks);
}
await startNode.StartExecution(Context);
// 等待结束
while (!MainCts.IsCancellationRequested)
if(FlipFlopCts != null)
{
await Task.Delay(100);
while (!FlipFlopCts.IsCancellationRequested)
{
await Task.Delay(100);
}
}
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
}
}
/// <summary>
@@ -140,17 +215,15 @@ namespace Serein.NodeFlow
/// </summary>
private async Task FlipflopExecute(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment flowEnvironment)
{
DynamicContext context = new DynamicContext(SereinIoc, flowEnvironment);
DynamicContext context = new DynamicContext(SereinIOC, flowEnvironment);
MethodDetails md = singleFlipFlopNode.MethodDetails;
var del = md.MethodDelegate;
try
{
//var func = md.ExplicitDatas.Length == 0 ? (Func<object, object, Task<FlipflopContext<dynamic>>>)del : (Func<object, object[], Task<FlipflopContext<dynamic>>>)del;
var func = md.ExplicitDatas.Length == 0 ? (Func<object, object, Task<IFlipflopContext>>)del : (Func<object, object[], Task<IFlipflopContext>>)del;
while (!MainCts.IsCancellationRequested) // 循环中直到栈为空才会退出
while (!FlipFlopCts.IsCancellationRequested) // 循环中直到栈为空才会退出
{
object?[]? parameters = singleFlipFlopNode.GetParameters(context, md);
// 调用委托并获取结果
@@ -168,7 +241,7 @@ namespace Serein.NodeFlow
var tasks = singleFlipFlopNode.SuccessorNodes[connection].Select(nextNode =>
{
var context = new DynamicContext(SereinIoc,flowEnvironment);
var context = new DynamicContext(SereinIOC,flowEnvironment);
nextNode.PreviousNode = singleFlipFlopNode;
return nextNode.StartExecution(context);
}).ToArray();

View File

@@ -7,16 +7,6 @@ using System.Reflection;
namespace Serein.NodeFlow.Tool;
//public static class DelegateCache
//{
// /// <summary>
// /// 委托缓存全局字典
// /// </summary>
// //public static ConcurrentDictionary<string, Delegate> GlobalDicDelegates { get; } = new ConcurrentDictionary<string, Delegate>();
//}
public static class MethodDetailsHelperTmp
{
/// <summary>
@@ -211,190 +201,3 @@ public static class MethodDetailsHelperTmp
}
public static class MethodDetailsHelper
{
// 缓存的实例对象(键:类型名称)
// public static ConcurrentDictionary<string, object> DynamicInstanceToType { get; } = new ConcurrentDictionary<string, object>();
// 缓存的实例对象 (键:生成的方法名称)
// public static ConcurrentDictionary<string, object> DynamicInstance { get; } = new ConcurrentDictionary<string, object>();
/// <summary>
/// 生成方法信息
/// </summary>
/// <param name="serviceContainer"></param>
/// <param name="type"></param>
/// <returns></returns>
public static ConcurrentDictionary<string, MethodDetails> GetDict(ISereinIoc serviceContainer, Type type, bool isNetFramework)
{
var methodDetailsDictionary = new ConcurrentDictionary<string, MethodDetails>();
var assemblyName = type.Assembly.GetName().Name;
var methods = GetMethodsToProcess(type, isNetFramework);
foreach (var method in methods)
{
var methodDetails = CreateMethodDetails(serviceContainer, type, method, assemblyName, isNetFramework);
methodDetailsDictionary.TryAdd(methodDetails.MethodName, methodDetails);
}
return methodDetailsDictionary;
}
/// <summary>
/// 获取处理方法
/// </summary>
private static IEnumerable<MethodInfo> GetMethodsToProcess(Type type, bool isNetFramework)
{
if (isNetFramework)
{
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(m => m.GetCustomAttribute<NodeActionAttribute>()?.Scan == true);
}
else
{
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(m => m.GetCustomAttribute<NodeActionAttribute>()?.Scan == true);
}
}
/// <summary>
/// 创建方法信息
/// </summary>
/// <returns></returns>
private static MethodDetails CreateMethodDetails(ISereinIoc serviceContainer, Type type, MethodInfo method, string assemblyName, bool isNetFramework)
{
var methodName = method.Name;
var attribute = method.GetCustomAttribute<NodeActionAttribute>();
var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters());
// 生成委托
var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型
method, // 方法信息
method.GetParameters(),// 方法参数
method.ReturnType);// 返回值
var dllTypeName = $"{assemblyName}.{type.Name}";
serviceContainer.Register(type);
object instance = serviceContainer.GetOrCreateServiceInstance(type);
var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}";
return new MethodDetails
{
ActingInstanceType = type,
ActingInstance = instance,
MethodName = dllTypeMethodName,
MethodDelegate = methodDelegate,
MethodDynamicType = attribute.MethodDynamicType,
MethodLockName = attribute.LockName,
MethodTips = attribute.MethodTips,
ExplicitDatas = explicitDataOfParameters,
ReturnType = method.ReturnType,
};
}
private static ExplicitData[] GetExplicitDataOfParameters(ParameterInfo[] parameters)
{
return parameters.Select((it, index) =>
{
//Console.WriteLine($"{it.Name}-{it.HasDefaultValue}-{it.DefaultValue}");
string explicitTypeName = GetExplicitTypeName(it.ParameterType);
var items = GetExplicitItems(it.ParameterType, explicitTypeName);
if ("Bool".Equals(explicitTypeName)) explicitTypeName = "Select"; // 布尔值 转为 可选类型
return new ExplicitData
{
IsExplicitData = it.HasDefaultValue,
Index = index,
ExplicitType = it.ParameterType,
ExplicitTypeName = explicitTypeName,
DataType = it.ParameterType,
ParameterName = it.Name,
DataValue = it.HasDefaultValue ? it.DefaultValue.ToString() : "",
Items = items.ToArray(),
};
}).ToArray();
}
private static string GetExplicitTypeName(Type type)
{
return type switch
{
Type t when t.IsEnum => "Select",
Type t when t == typeof(bool) => "Bool",
Type t when t == typeof(string) => "Value",
Type t when t == typeof(int) => "Value",
Type t when t == typeof(double) => "Value",
_ => "Value"
};
}
private static IEnumerable<string> GetExplicitItems(Type type, string explicitTypeName)
{
return explicitTypeName switch
{
"Select" => Enum.GetNames(type),
"Bool" => ["True", "False"],
_ => []
};
}
private static Delegate GenerateMethodDelegate(Type type, MethodInfo methodInfo, ParameterInfo[] parameters, Type returnType)
{
var parameterTypes = parameters.Select(p => p.ParameterType).ToArray();
var parameterCount = parameters.Length;
if (returnType == typeof(void))
{
if (parameterCount == 0)
{
// 无返回值,无参数
return ExpressionHelper.MethodCaller(type, methodInfo);
}
else
{
// 无返回值,有参数
return ExpressionHelper.MethodCaller(type, methodInfo, parameterTypes);
}
}
// else if (returnType == typeof(Task<FlipflopContext)) // 触发器
else if (FlipflopFunc.IsTaskOfFlipflop(returnType)) // 触发器
{
if (parameterCount == 0)
{
// 有返回值,无参数
return ExpressionHelper.MethodCallerAsync(type, methodInfo);
}
else
{
// 有返回值,有参数
return ExpressionHelper.MethodCallerAsync(type, methodInfo, parameterTypes);
}
}
else
{
if (parameterCount == 0)
{
// 有返回值,无参数
return ExpressionHelper.MethodCallerHaveResult(type, methodInfo);
}
else
{
// 有返回值,有参数
return ExpressionHelper.MethodCallerHaveResult(type, methodInfo, parameterTypes);
}
}
}
}