2024-09-12 20:32:54 +08:00
|
|
|
|
using Serein.Library.Api;
|
|
|
|
|
|
using Serein.Library.Attributes;
|
|
|
|
|
|
using Serein.Library.Core.NodeFlow;
|
2024-09-15 12:15:32 +08:00
|
|
|
|
using Serein.Library.Entity;
|
2024-10-10 10:45:53 +08:00
|
|
|
|
using Serein.Library.Utils;
|
2024-09-27 10:30:19 +08:00
|
|
|
|
using System;
|
2024-08-06 16:09:46 +08:00
|
|
|
|
using System.Collections.Concurrent;
|
2024-09-28 23:55:19 +08:00
|
|
|
|
using System.ComponentModel;
|
2024-08-06 16:09:46 +08:00
|
|
|
|
using System.Reflection;
|
2024-10-07 15:15:18 +08:00
|
|
|
|
using System.Text.RegularExpressions;
|
2024-08-06 16:09:46 +08:00
|
|
|
|
|
|
|
|
|
|
namespace Serein.NodeFlow.Tool;
|
|
|
|
|
|
|
2024-10-10 10:45:53 +08:00
|
|
|
|
public static class MethodDetailsHelper
|
2024-08-06 16:09:46 +08:00
|
|
|
|
{
|
2024-09-30 02:45:49 +08:00
|
|
|
|
|
2024-08-06 16:09:46 +08:00
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 生成方法信息
|
2024-08-06 16:09:46 +08:00
|
|
|
|
/// </summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <param name="serviceContainer"></param>
|
|
|
|
|
|
/// <param name="type"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2024-09-30 02:45:49 +08:00
|
|
|
|
//public static List<MethodDetails> GetList(Type type)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var methodDetailsDictionary = new List<MethodDetails>();
|
|
|
|
|
|
// var delegateDictionary = new List<Delegate>();
|
|
|
|
|
|
// var assemblyName = type.Assembly.GetName().Name;
|
|
|
|
|
|
// var methods = GetMethodsToProcess(type);
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-30 02:45:49 +08:00
|
|
|
|
// foreach (var method in methods)
|
|
|
|
|
|
// {
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-30 02:45:49 +08:00
|
|
|
|
// (var methodDetails,var methodDelegate) = CreateMethodDetails(type, method, assemblyName);
|
|
|
|
|
|
|
|
|
|
|
|
// methodDetailsDictionary.Add(methodDetails);
|
|
|
|
|
|
// delegateDictionary.Add(methodDelegate);
|
|
|
|
|
|
// }
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-30 02:45:49 +08:00
|
|
|
|
// var mds = methodDetailsDictionary.OrderBy(it => it.MethodName).ToList();
|
|
|
|
|
|
// var dels = delegateDictionary;
|
|
|
|
|
|
|
|
|
|
|
|
// return mds;
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取处理方法
|
|
|
|
|
|
/// </summary>
|
2024-09-30 02:45:49 +08:00
|
|
|
|
public static IEnumerable<MethodInfo> GetMethodsToProcess(Type type)
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-09-25 22:20:23 +08:00
|
|
|
|
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
2024-09-15 12:15:32 +08:00
|
|
|
|
.Where(m => m.GetCustomAttribute<NodeActionAttribute>()?.Scan == true);
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建方法信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2024-10-10 10:45:53 +08:00
|
|
|
|
public static (MethodDetails?, DelegateDetails?) CreateMethodDetails(Type type, MethodInfo method, string assemblyName)
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
var attribute = method.GetCustomAttribute<NodeActionAttribute>();
|
2024-09-15 22:07:10 +08:00
|
|
|
|
if(attribute is null)
|
|
|
|
|
|
{
|
2024-09-30 02:45:49 +08:00
|
|
|
|
return (null, null);
|
2024-09-15 22:07:10 +08:00
|
|
|
|
}
|
2024-10-07 15:15:18 +08:00
|
|
|
|
//var dllTypeName = $"{assemblyName}.{type.Name}";
|
|
|
|
|
|
var dllTypeMethodName = $"{assemblyName}.{type.Name}.{method.Name}";
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters());
|
2024-10-10 10:45:53 +08:00
|
|
|
|
//// 通过表达式树生成委托
|
|
|
|
|
|
//var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型
|
|
|
|
|
|
// method, // 方法信息
|
|
|
|
|
|
// method.GetParameters(),// 方法参数
|
|
|
|
|
|
// method.ReturnType);// 返回值
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-10-10 10:45:53 +08:00
|
|
|
|
//// 通过表达式树生成委托
|
|
|
|
|
|
var emitMethodType = EmitHelper.CreateDynamicMethod(method, out var methodDelegate);// 返回值
|
2024-10-07 15:15:18 +08:00
|
|
|
|
|
2024-10-07 22:52:10 +08:00
|
|
|
|
Type? returnType;
|
2024-10-07 15:15:18 +08:00
|
|
|
|
bool isTask = IsGenericTask(method.ReturnType, out var taskResult);
|
|
|
|
|
|
|
|
|
|
|
|
if (attribute.MethodDynamicType == Library.Enums.NodeType.Flipflop)
|
2024-09-15 22:07:10 +08:00
|
|
|
|
{
|
|
|
|
|
|
returnType = attribute.ReturnType;
|
2024-10-07 15:15:18 +08:00
|
|
|
|
if (!isTask || taskResult != typeof(IFlipflopContext))
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine($"触发器节点的返回类型非预期类型,可能会导致流程异常。[{dllTypeMethodName}]当前返回类型为[{method.ReturnType}],而预期的返回类型应为[Task<IFlipflopContext>]");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else if(isTask)
|
|
|
|
|
|
{
|
2024-10-07 22:52:10 +08:00
|
|
|
|
returnType = taskResult is null ? typeof(Task) : taskResult;
|
2024-09-15 22:07:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
returnType = method.ReturnType;
|
|
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-10-07 15:15:18 +08:00
|
|
|
|
if (string.IsNullOrEmpty(attribute.MethodTips)){
|
|
|
|
|
|
attribute.MethodTips = method.Name;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var asyncPrefix = "[异步]"; // IsGenericTask(returnType) ? "[async]" : ;
|
|
|
|
|
|
var methodTips = isTask ? asyncPrefix + attribute.MethodTips : attribute.MethodTips;
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-30 02:45:49 +08:00
|
|
|
|
var md = new MethodDetails
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
ActingInstanceType = type,
|
2024-09-15 19:48:27 +08:00
|
|
|
|
// ActingInstance = instance,
|
2024-09-15 12:15:32 +08:00
|
|
|
|
MethodName = dllTypeMethodName,
|
|
|
|
|
|
MethodDynamicType = attribute.MethodDynamicType,
|
|
|
|
|
|
MethodLockName = attribute.LockName,
|
2024-10-07 15:15:18 +08:00
|
|
|
|
MethodTips = methodTips,
|
2024-09-15 12:15:32 +08:00
|
|
|
|
ExplicitDatas = explicitDataOfParameters,
|
2024-09-15 22:07:10 +08:00
|
|
|
|
ReturnType = returnType,
|
2024-09-15 12:15:32 +08:00
|
|
|
|
};
|
2024-10-10 10:45:53 +08:00
|
|
|
|
var dd = new DelegateDetails( emitMethodType, methodDelegate) ;
|
|
|
|
|
|
return (md, dd);
|
2024-09-30 02:45:49 +08:00
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-07 22:52:10 +08:00
|
|
|
|
public static bool IsGenericTask(Type returnType, out Type? taskResult)
|
2024-10-07 15:15:18 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 判断是否为 Task 类型或泛型 Task<T>
|
|
|
|
|
|
if (returnType == typeof(Task))
|
|
|
|
|
|
{
|
2024-10-07 22:52:10 +08:00
|
|
|
|
taskResult = null;
|
2024-10-07 15:15:18 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
|
|
|
|
|
{
|
|
|
|
|
|
// 获取泛型参数类型
|
|
|
|
|
|
Type genericArgument = returnType.GetGenericArguments()[0];
|
|
|
|
|
|
taskResult = genericArgument;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
taskResult = null;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-28 23:55:19 +08:00
|
|
|
|
|
|
|
|
|
|
private static ConcurrentDictionary<string, (object, MethodInfo)> ConvertorInstance =[];
|
|
|
|
|
|
|
2024-09-25 22:20:23 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取参数信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="parameters"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
private static ExplicitData[] GetExplicitDataOfParameters(ParameterInfo[] parameters)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
return parameters.Select((it, index) =>
|
|
|
|
|
|
{
|
2024-09-25 22:20:23 +08:00
|
|
|
|
Type paremType;
|
2024-09-28 23:55:19 +08:00
|
|
|
|
|
|
|
|
|
|
if (it.GetCustomAttribute<EnumTypeConvertorAttribute>() is EnumTypeConvertorAttribute attribute1 && attribute1 is not null)
|
2024-09-27 10:30:19 +08:00
|
|
|
|
{
|
2024-09-28 23:55:19 +08:00
|
|
|
|
// 存在类型选择器
|
|
|
|
|
|
paremType = attribute1.EnumType;
|
|
|
|
|
|
return GetExplicitDataOfParameter(it, index, paremType, true);
|
2024-09-27 10:30:19 +08:00
|
|
|
|
}
|
2024-09-28 23:55:19 +08:00
|
|
|
|
else if (it.GetCustomAttribute<BindConvertorAttribute>() is BindConvertorAttribute attribute2 && attribute2 is not null)
|
2024-09-27 10:30:19 +08:00
|
|
|
|
{
|
2024-09-28 23:55:19 +08:00
|
|
|
|
paremType = attribute2.EnumType;
|
|
|
|
|
|
|
|
|
|
|
|
string key = typeof(IEnumConvertor<,>).FullName + attribute2.EnumType.FullName + attribute2.ConvertorType.FullName;
|
|
|
|
|
|
|
|
|
|
|
|
if (!ConvertorInstance.ContainsKey(key))
|
|
|
|
|
|
{
|
|
|
|
|
|
Type enumConvertorType = typeof(IEnumConvertor<,>);
|
|
|
|
|
|
// 定义具体类型
|
|
|
|
|
|
Type specificType = enumConvertorType.MakeGenericType(attribute2.EnumType, it.ParameterType);
|
|
|
|
|
|
// 获取实现类的类型
|
|
|
|
|
|
Type implementorType = attribute2.ConvertorType;
|
|
|
|
|
|
// 创建实现类的实例
|
|
|
|
|
|
object instance = Activator.CreateInstance(implementorType);
|
|
|
|
|
|
// 调用 Convert 方法
|
|
|
|
|
|
MethodInfo convertMethod = implementorType.GetMethod("Convertor");
|
|
|
|
|
|
ConvertorInstance[key] = (instance, convertMethod);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Func<object, object> func = (enumValue) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
(var obj,var methodInfo) = ConvertorInstance[key];
|
|
|
|
|
|
return methodInfo?.Invoke(obj, [enumValue]);
|
|
|
|
|
|
};
|
|
|
|
|
|
// 确保实例实现了所需接口
|
|
|
|
|
|
ExplicitData ed = GetExplicitDataOfParameter(it, index, paremType, true, func);
|
|
|
|
|
|
|
|
|
|
|
|
return ed;
|
2024-09-27 10:30:19 +08:00
|
|
|
|
}
|
2024-09-28 23:55:19 +08:00
|
|
|
|
else
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-09-28 23:55:19 +08:00
|
|
|
|
return GetExplicitDataOfParameter(it, index, it.ParameterType, it.HasDefaultValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
//string explicitTypeName = GetExplicitTypeName(paremType);
|
|
|
|
|
|
//var items = GetExplicitItems(paremType, explicitTypeName);
|
|
|
|
|
|
//if ("Bool".Equals(explicitTypeName)) explicitTypeName = "Select"; // 布尔值 转为 可选类型
|
|
|
|
|
|
//return new ExplicitData
|
|
|
|
|
|
//{
|
|
|
|
|
|
// IsExplicitData = attribute is null ? it.HasDefaultValue: true,
|
|
|
|
|
|
// Index = index,
|
|
|
|
|
|
// ExplicitTypeName = explicitTypeName,
|
|
|
|
|
|
// ExplicitType = paremType,
|
|
|
|
|
|
// DataType = it.ParameterType,
|
|
|
|
|
|
// ParameterName = it.Name,
|
|
|
|
|
|
// DataValue = it.HasDefaultValue ? it?.DefaultValue?.ToString() : "",
|
|
|
|
|
|
// Items = items.ToArray(),
|
|
|
|
|
|
//};
|
|
|
|
|
|
}).ToArray();
|
|
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-28 23:55:19 +08:00
|
|
|
|
private static ExplicitData GetExplicitDataOfParameter(ParameterInfo parameterInfo,
|
|
|
|
|
|
int index,
|
|
|
|
|
|
Type paremType,
|
|
|
|
|
|
bool isExplicitData,
|
|
|
|
|
|
Func<object, object> func = null)
|
|
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-28 23:55:19 +08:00
|
|
|
|
string explicitTypeName = GetExplicitTypeName(paremType);
|
|
|
|
|
|
var items = GetExplicitItems(paremType, explicitTypeName);
|
|
|
|
|
|
if ("Bool".Equals(explicitTypeName)) explicitTypeName = "Select"; // 布尔值 转为 可选类型
|
|
|
|
|
|
return new ExplicitData
|
|
|
|
|
|
{
|
|
|
|
|
|
IsExplicitData = isExplicitData, //attribute is null ? parameterInfo.HasDefaultValue : true,
|
|
|
|
|
|
Index = index,
|
|
|
|
|
|
ExplicitTypeName = explicitTypeName,
|
|
|
|
|
|
ExplicitType = paremType,
|
|
|
|
|
|
Convertor = func,
|
|
|
|
|
|
DataType = parameterInfo.ParameterType,
|
|
|
|
|
|
ParameterName = parameterInfo.Name,
|
|
|
|
|
|
DataValue = parameterInfo.HasDefaultValue ? parameterInfo?.DefaultValue?.ToString() : "",
|
|
|
|
|
|
Items = items.ToArray(),
|
|
|
|
|
|
};
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-28 23:55:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-09-25 22:20:23 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 判断使用输入器还是选择器
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="type"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
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"
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-25 22:20:23 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取参数列表选项
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="type"></param>
|
|
|
|
|
|
/// <param name="explicitTypeName"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
private static IEnumerable<string> GetExplicitItems(Type type, string explicitTypeName)
|
|
|
|
|
|
{
|
2024-09-25 22:20:23 +08:00
|
|
|
|
IEnumerable<string> items = explicitTypeName switch
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
"Select" => Enum.GetNames(type),
|
|
|
|
|
|
"Bool" => ["True", "False"],
|
|
|
|
|
|
_ => []
|
|
|
|
|
|
};
|
2024-09-25 22:20:23 +08:00
|
|
|
|
return items;
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-10 10:45:53 +08:00
|
|
|
|
//private static Delegate GenerateMethodDelegate(Type type, MethodInfo methodInfo, ParameterInfo[] parameters, Type returnType)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var parameterTypes = parameters.Select(p => p.ParameterType).ToArray();
|
|
|
|
|
|
// var parameterCount = parameters.Length;
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-10-10 10:45:53 +08:00
|
|
|
|
// 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);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-08-06 16:09:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|