2024-10-10 10:45:53 +08:00
|
|
|
|
using System;
|
2025-07-31 23:59:31 +08:00
|
|
|
|
using System.Collections;
|
2024-10-10 10:45:53 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
2024-11-02 16:48:40 +08:00
|
|
|
|
using System.Reactive;
|
2024-10-10 10:45:53 +08:00
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
using System.Reflection.Emit;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Serein.Library.Utils
|
|
|
|
|
|
{
|
2025-07-30 21:15:07 +08:00
|
|
|
|
|
2024-10-11 19:31:34 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Emit创建委托工具类
|
|
|
|
|
|
/// </summary>
|
2024-10-10 10:45:53 +08:00
|
|
|
|
public class EmitHelper
|
|
|
|
|
|
{
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 动态方法信息
|
|
|
|
|
|
/// </summary>
|
2024-12-20 23:39:29 +08:00
|
|
|
|
public class EmitMethodInfo
|
|
|
|
|
|
{
|
2025-07-18 22:45:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 方法声明类型
|
|
|
|
|
|
/// </summary>
|
2024-12-20 23:39:29 +08:00
|
|
|
|
public Type DeclaringType { get; set; }
|
2025-07-18 22:45:06 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 方法类型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public EmitMethodType EmitMethodType { get; set; }
|
|
|
|
|
|
|
2024-12-20 23:39:29 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 是异步方法
|
|
|
|
|
|
/// </summary>
|
2025-07-18 22:45:06 +08:00
|
|
|
|
public bool IsAsync { get; set; }
|
2024-12-20 23:39:29 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 是静态的
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public bool IsStatic { get; set; }
|
2025-07-18 22:45:06 +08:00
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
|
|
|
|
|
|
public bool HasByRefParameters { get; set; }
|
|
|
|
|
|
public int[] ByRefParameterIndexes { get; set; } = [];
|
2024-12-20 23:39:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 方法类型枚举
|
|
|
|
|
|
/// </summary>
|
2024-10-10 10:45:53 +08:00
|
|
|
|
public enum EmitMethodType
|
|
|
|
|
|
{
|
2024-10-11 19:31:34 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 普通的方法。如果方法返回void时,将会返回null。
|
|
|
|
|
|
/// </summary>
|
2024-10-10 10:45:53 +08:00
|
|
|
|
Func,
|
2024-10-11 19:31:34 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 无返回值的异步方法
|
|
|
|
|
|
/// </summary>
|
2024-10-10 10:45:53 +08:00
|
|
|
|
Task,
|
2024-10-11 19:31:34 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 有返回值的异步方法
|
|
|
|
|
|
/// </summary>
|
2025-07-18 22:45:06 +08:00
|
|
|
|
TaskHasResult,
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
2024-11-02 22:11:38 +08:00
|
|
|
|
|
2026-01-27 17:36:16 +08:00
|
|
|
|
static Task<object> ConvertTaskResult<T>(Task<T> task) where T : class
|
|
|
|
|
|
{
|
|
|
|
|
|
return task.ContinueWith(t => (object)t.Result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-30 21:15:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 判断一个类型是否为泛型 Task<T> 或 Task,并返回泛型参数类型(如果有的话)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="returnType"></param>
|
|
|
|
|
|
/// <param name="taskResult"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
#nullable enable
|
|
|
|
|
|
public static bool IsGenericTask(Type returnType, out Type? taskResult)
|
2024-10-10 10:45:53 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 判断是否为 Task 类型或泛型 Task<T>
|
|
|
|
|
|
if (returnType == typeof(Task))
|
|
|
|
|
|
{
|
2025-07-30 21:15:07 +08:00
|
|
|
|
taskResult = typeof(void);
|
2024-10-10 10:45:53 +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-11-02 22:11:38 +08:00
|
|
|
|
|
2024-10-14 17:29:28 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据方法信息创建动态调用的委托,返回方法类型,以及传出一个委托
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="methodInfo"></param>
|
|
|
|
|
|
/// <param name="delegate"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2026-01-27 17:33:48 +08:00
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static EmitMethodInfo CreateMethod(MethodInfo methodInfo, out Delegate @delegate)
|
2024-10-10 10:45:53 +08:00
|
|
|
|
{
|
2025-07-30 21:15:07 +08:00
|
|
|
|
if (methodInfo.DeclaringType == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(methodInfo.DeclaringType));
|
2026-01-27 17:33:48 +08:00
|
|
|
|
|
|
|
|
|
|
bool isStatic = methodInfo.IsStatic;
|
|
|
|
|
|
bool isTask = IsGenericTask(methodInfo.ReturnType, out var taskResultType);
|
|
|
|
|
|
bool isTaskGeneric = taskResultType != null;
|
|
|
|
|
|
|
|
|
|
|
|
Type dynamicReturnType;
|
|
|
|
|
|
if (!isTask)
|
|
|
|
|
|
dynamicReturnType = typeof(object);
|
2024-11-02 16:48:40 +08:00
|
|
|
|
else
|
2026-01-27 17:33:48 +08:00
|
|
|
|
dynamicReturnType = isTaskGeneric ? typeof(Task<object>) : typeof(Task);
|
|
|
|
|
|
|
|
|
|
|
|
var dynamicMethod = new DynamicMethod(
|
|
|
|
|
|
methodInfo.Name + "_Emit",
|
|
|
|
|
|
dynamicReturnType,
|
|
|
|
|
|
new[] { typeof(object), typeof(object[]) },
|
|
|
|
|
|
restrictedSkipVisibility: true);
|
|
|
|
|
|
|
|
|
|
|
|
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
|
|
|
|
var parameters = methodInfo.GetParameters();
|
|
|
|
|
|
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
// 1. 声明 ref / out / in 局部变量
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
LocalBuilder?[] locals = new LocalBuilder?[parameters.Length];
|
|
|
|
|
|
List<int> byRefIndexes = new();
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < parameters.Length; i++)
|
2024-10-10 10:45:53 +08:00
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
if (parameters[i].ParameterType.IsByRef)
|
2024-10-10 10:45:53 +08:00
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
var elementType = parameters[i].ParameterType.GetElementType()!;
|
|
|
|
|
|
locals[i] = il.DeclareLocal(elementType);
|
|
|
|
|
|
byRefIndexes.Add(i);
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
// ==============================
|
|
|
|
|
|
// 2. 初始化 ref / in 参数
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
for (int i = 0; i < parameters.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var p = parameters[i];
|
|
|
|
|
|
if (!p.ParameterType.IsByRef || p.IsOut)
|
|
|
|
|
|
continue;
|
2024-11-02 22:11:38 +08:00
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
|
il.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
|
il.Emit(OpCodes.Ldelem_Ref);
|
2024-11-02 22:11:38 +08:00
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
var elementType = p.ParameterType.GetElementType()!;
|
|
|
|
|
|
if (elementType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, elementType);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, elementType);
|
2024-10-10 10:45:53 +08:00
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
il.Emit(OpCodes.Stloc, locals[i]!);
|
2024-12-20 23:39:29 +08:00
|
|
|
|
}
|
2026-01-27 17:33:48 +08:00
|
|
|
|
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
// 3. 加载实例
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
if (!isStatic)
|
2024-12-20 23:39:29 +08:00
|
|
|
|
{
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
2026-01-27 17:33:48 +08:00
|
|
|
|
il.Emit(OpCodes.Castclass, methodInfo.DeclaringType);
|
2024-12-20 23:39:29 +08:00
|
|
|
|
}
|
2024-10-10 10:45:53 +08:00
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
// ==============================
|
|
|
|
|
|
// 4. 加载参数
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
for (int i = 0; i < parameters.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var p = parameters[i];
|
|
|
|
|
|
if (p.ParameterType.IsByRef)
|
2024-10-10 10:45:53 +08:00
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
il.Emit(OpCodes.Ldloca, locals[i]!);
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
2026-01-27 17:33:48 +08:00
|
|
|
|
else
|
2024-10-10 10:45:53 +08:00
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
|
il.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
|
il.Emit(OpCodes.Ldelem_Ref);
|
2024-11-02 22:11:38 +08:00
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
if (p.ParameterType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, p.ParameterType);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, p.ParameterType);
|
|
|
|
|
|
}
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
// ==============================
|
|
|
|
|
|
// 5. 调用方法
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
il.Emit(isStatic ? OpCodes.Call : OpCodes.Callvirt, methodInfo);
|
|
|
|
|
|
|
2026-01-27 17:36:16 +08:00
|
|
|
|
// 如果是泛型Task
|
2026-01-27 18:00:16 +08:00
|
|
|
|
if (isTaskGeneric && methodInfo.ReturnType.IsValueType && taskResultType is not null)
|
2026-01-27 17:36:16 +08:00
|
|
|
|
{
|
|
|
|
|
|
var convertMethod = typeof(EmitHelper)
|
|
|
|
|
|
.GetMethod(nameof(ConvertTaskResult),
|
|
|
|
|
|
BindingFlags.Static | BindingFlags.NonPublic)!
|
|
|
|
|
|
.MakeGenericMethod(taskResultType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Call, convertMethod);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
// ==============================
|
|
|
|
|
|
// 6. 回写 ref / out 参数
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
for (int i = 0; i < parameters.Length; i++)
|
2024-12-20 23:39:29 +08:00
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
if (!parameters[i].ParameterType.IsByRef)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
var elementType = parameters[i].ParameterType.GetElementType()!;
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
|
il.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
|
il.Emit(OpCodes.Ldloc, locals[i]!);
|
|
|
|
|
|
|
|
|
|
|
|
if (elementType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Box, elementType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Stelem_Ref);
|
2024-12-20 23:39:29 +08:00
|
|
|
|
}
|
2024-10-10 10:45:53 +08:00
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
// ==============================
|
|
|
|
|
|
// 7. 处理返回值
|
|
|
|
|
|
// ==============================
|
2024-10-10 10:45:53 +08:00
|
|
|
|
if (methodInfo.ReturnType == typeof(void))
|
|
|
|
|
|
{
|
|
|
|
|
|
il.Emit(OpCodes.Ldnull);
|
|
|
|
|
|
}
|
2026-01-27 17:33:48 +08:00
|
|
|
|
else if (!isTask && methodInfo.ReturnType.IsValueType)
|
2024-10-10 10:45:53 +08:00
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
il.Emit(OpCodes.Box, methodInfo.ReturnType);
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
2026-01-27 17:33:48 +08:00
|
|
|
|
|
2026-01-27 17:36:16 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-01-27 17:33:48 +08:00
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
// 8. 创建委托
|
|
|
|
|
|
// ==============================
|
|
|
|
|
|
EmitMethodType emitType;
|
|
|
|
|
|
if (!isTask)
|
2024-10-10 10:45:53 +08:00
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
emitType = EmitMethodType.Func;
|
|
|
|
|
|
@delegate = dynamicMethod.CreateDelegate(
|
|
|
|
|
|
typeof(Func<object, object[], object>));
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (isTaskGeneric)
|
|
|
|
|
|
{
|
|
|
|
|
|
emitType = EmitMethodType.TaskHasResult;
|
|
|
|
|
|
@delegate = dynamicMethod.CreateDelegate(
|
|
|
|
|
|
typeof(Func<object, object[], Task<object>>));
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
emitType = EmitMethodType.Task;
|
|
|
|
|
|
@delegate = dynamicMethod.CreateDelegate(
|
|
|
|
|
|
typeof(Func<object, object[], Task>));
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
2026-01-27 17:33:48 +08:00
|
|
|
|
|
2024-12-20 23:39:29 +08:00
|
|
|
|
return new EmitMethodInfo
|
|
|
|
|
|
{
|
2026-01-27 17:33:48 +08:00
|
|
|
|
EmitMethodType = emitType,
|
2024-12-20 23:39:29 +08:00
|
|
|
|
DeclaringType = methodInfo.DeclaringType,
|
2026-01-27 17:33:48 +08:00
|
|
|
|
IsAsync = isTask,
|
|
|
|
|
|
IsStatic = isStatic,
|
|
|
|
|
|
HasByRefParameters = byRefIndexes.Count > 0,
|
|
|
|
|
|
ByRefParameterIndexes = byRefIndexes.ToArray()
|
2024-12-20 23:39:29 +08:00
|
|
|
|
};
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-26 19:36:54 +08:00
|
|
|
|
/// <summary>
|
2025-07-31 11:21:49 +08:00
|
|
|
|
/// 构建字段 Getter 委托:Func<object, object>
|
2025-07-26 19:36:54 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static Func<object, object> CreateFieldGetter(FieldInfo fieldInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (fieldInfo == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(fieldInfo));
|
2025-07-30 21:15:07 +08:00
|
|
|
|
|
|
|
|
|
|
if (fieldInfo.DeclaringType == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(fieldInfo.DeclaringType));
|
|
|
|
|
|
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
|
|
|
|
|
var method = new DynamicMethod(
|
|
|
|
|
|
fieldInfo.Name + "_Get",
|
|
|
|
|
|
typeof(object),
|
|
|
|
|
|
new[] { typeof(object) },
|
|
|
|
|
|
fieldInfo.DeclaringType,
|
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
|
|
ILGenerator il = method.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
|
|
if (!fieldInfo.IsStatic)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 加载实例
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, fieldInfo.DeclaringType);
|
|
|
|
|
|
il.Emit(OpCodes.Ldfld, fieldInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
il.Emit(OpCodes.Ldsfld, fieldInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果是值类型,装箱
|
|
|
|
|
|
if (fieldInfo.FieldType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Box, fieldInfo.FieldType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
|
|
|
|
|
|
return (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-07-31 11:21:49 +08:00
|
|
|
|
/// 构建字段 Setter 委托:Action<object, object>
|
2025-07-26 19:36:54 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static Action<object, object> CreateFieldSetter(FieldInfo fieldInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (fieldInfo == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(fieldInfo));
|
2025-07-30 21:15:07 +08:00
|
|
|
|
if (fieldInfo.DeclaringType == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(fieldInfo.DeclaringType));
|
2025-07-26 19:36:54 +08:00
|
|
|
|
if (fieldInfo.IsInitOnly)
|
|
|
|
|
|
throw new InvalidOperationException($"字段 {fieldInfo.Name} 是只读字段,无法设置值。");
|
|
|
|
|
|
|
|
|
|
|
|
var method = new DynamicMethod(
|
|
|
|
|
|
fieldInfo.Name + "_Set",
|
|
|
|
|
|
null,
|
|
|
|
|
|
new[] { typeof(object), typeof(object) },
|
|
|
|
|
|
fieldInfo.DeclaringType,
|
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
|
|
ILGenerator il = method.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
|
|
if (!fieldInfo.IsStatic)
|
|
|
|
|
|
{
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, fieldInfo.DeclaringType);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 加载值
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
|
if (fieldInfo.FieldType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, fieldInfo.FieldType);
|
|
|
|
|
|
|
|
|
|
|
|
if (fieldInfo.IsStatic)
|
|
|
|
|
|
il.Emit(OpCodes.Stsfld, fieldInfo);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Stfld, fieldInfo);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
|
|
|
|
|
|
return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-07-31 11:21:49 +08:00
|
|
|
|
/// 构建属性 Getter 委托:Func<object, object>
|
2025-07-26 19:36:54 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static Func<object, object> CreatePropertyGetter(PropertyInfo propertyInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (propertyInfo == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(propertyInfo));
|
2025-07-30 21:15:07 +08:00
|
|
|
|
if (propertyInfo.DeclaringType == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(propertyInfo.DeclaringType));
|
2025-07-26 19:36:54 +08:00
|
|
|
|
var getMethod = propertyInfo.GetGetMethod(true);
|
|
|
|
|
|
if (getMethod == null)
|
|
|
|
|
|
throw new InvalidOperationException($"属性 {propertyInfo.Name} 没有可用的 Getter。");
|
|
|
|
|
|
|
|
|
|
|
|
var method = new DynamicMethod(
|
|
|
|
|
|
propertyInfo.Name + "_Get",
|
|
|
|
|
|
typeof(object),
|
|
|
|
|
|
new[] { typeof(object) },
|
|
|
|
|
|
propertyInfo.DeclaringType,
|
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
|
|
ILGenerator il = method.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
|
|
if (!getMethod.IsStatic)
|
|
|
|
|
|
{
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
|
|
|
|
|
|
il.EmitCall(OpCodes.Callvirt, getMethod, null);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
il.EmitCall(OpCodes.Call, getMethod, null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 装箱
|
|
|
|
|
|
if (propertyInfo.PropertyType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Box, propertyInfo.PropertyType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
|
|
|
|
|
|
return (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-07-31 11:21:49 +08:00
|
|
|
|
/// 构建属性 Setter 委托:Action<object, object>
|
2025-07-26 19:36:54 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static Action<object, object> CreatePropertySetter(PropertyInfo propertyInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (propertyInfo == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(propertyInfo));
|
2025-07-30 21:15:07 +08:00
|
|
|
|
if (propertyInfo.DeclaringType == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(propertyInfo.DeclaringType));
|
|
|
|
|
|
|
2025-07-26 19:36:54 +08:00
|
|
|
|
var setMethod = propertyInfo.GetSetMethod(true);
|
|
|
|
|
|
if (setMethod == null)
|
|
|
|
|
|
throw new InvalidOperationException($"属性 {propertyInfo.Name} 没有可用的 Setter。");
|
|
|
|
|
|
|
|
|
|
|
|
var method = new DynamicMethod(
|
|
|
|
|
|
propertyInfo.Name + "_Set",
|
|
|
|
|
|
null,
|
|
|
|
|
|
new[] { typeof(object), typeof(object) },
|
|
|
|
|
|
propertyInfo.DeclaringType,
|
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
|
|
ILGenerator il = method.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
|
|
if (!setMethod.IsStatic)
|
|
|
|
|
|
{
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 加载值
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
|
if (propertyInfo.PropertyType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
|
|
|
|
|
|
|
|
|
|
|
|
if (setMethod.IsStatic)
|
|
|
|
|
|
il.EmitCall(OpCodes.Call, setMethod, null);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.EmitCall(OpCodes.Callvirt, setMethod, null);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
|
|
|
|
|
|
return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-31 11:21:49 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 构建数组创建委托:Func<int, object[]>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="elementType"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
/// <exception cref="ArgumentNullException"></exception>
|
|
|
|
|
|
|
|
|
|
|
|
public static Func<int, object> CreateArrayFactory(Type elementType)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (elementType == null) throw new ArgumentNullException(nameof(elementType));
|
|
|
|
|
|
|
|
|
|
|
|
var arrayType = elementType.MakeArrayType();
|
|
|
|
|
|
|
|
|
|
|
|
var dm = new DynamicMethod(
|
|
|
|
|
|
$"NewArray_{elementType.Name}",
|
|
|
|
|
|
typeof(object), // 返回 object
|
|
|
|
|
|
new[] { typeof(int) }, // 参数:length
|
|
|
|
|
|
typeof(EmitHelper).Module,
|
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
|
|
var il = dm.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0); // length
|
|
|
|
|
|
il.Emit(OpCodes.Newarr, elementType); // new T[length]
|
|
|
|
|
|
il.Emit(OpCodes.Ret); // 返回 T[]
|
|
|
|
|
|
|
|
|
|
|
|
return (Func<int, object>)dm.CreateDelegate(typeof(Func<int, object>));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-07-31 11:21:49 +08:00
|
|
|
|
/// 构建集合赋值委托:Action<object, object, object>
|
2025-07-26 19:36:54 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="collectionType"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
/// <exception cref="NotSupportedException"></exception>
|
|
|
|
|
|
public static Action<object, object, object> CreateCollectionSetter(Type collectionType)
|
|
|
|
|
|
{
|
|
|
|
|
|
DynamicMethod dm = new DynamicMethod(
|
|
|
|
|
|
"SetCollectionValue",
|
|
|
|
|
|
null,
|
|
|
|
|
|
new[] { typeof(object), typeof(object), typeof(object) },
|
|
|
|
|
|
typeof(EmitHelper).Module,
|
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
|
|
ILGenerator il = dm.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
|
|
if (collectionType.IsArray)
|
|
|
|
|
|
{
|
|
|
|
|
|
// (object array, object index, object value) => ((T[])array)[(int)index] = (T)value;
|
|
|
|
|
|
var elementType = collectionType.GetElementType()!;
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, collectionType); // 转为真实数组类型
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, typeof(int)); // index
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_2);
|
|
|
|
|
|
if (elementType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, elementType);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, elementType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Stelem, elementType); // 设置数组元素
|
|
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 尝试获取 set_Item 方法
|
|
|
|
|
|
MethodInfo? setItem = collectionType.GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public);
|
|
|
|
|
|
if (setItem == null)
|
|
|
|
|
|
throw new NotSupportedException($"类型 {collectionType} 不支持 set_Item。");
|
|
|
|
|
|
|
|
|
|
|
|
var parameters = setItem.GetParameters();
|
|
|
|
|
|
var indexType = parameters[0].ParameterType;
|
|
|
|
|
|
var valueType = parameters[1].ParameterType;
|
|
|
|
|
|
|
|
|
|
|
|
// (object collection, object index, object value) => ((CollectionType)collection)[(IndexType)index] = (ValueType)value;
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, collectionType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
|
if (indexType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, indexType);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, indexType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_2);
|
|
|
|
|
|
if (valueType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, valueType);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, valueType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Callvirt, setItem);
|
|
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (Action<object, object, object>)dm.CreateDelegate(typeof(Action<object, object, object>));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-07-31 23:59:31 +08:00
|
|
|
|
/// 构建集合取值委托:(object collection, object index) => object value
|
|
|
|
|
|
/// 支持数组、泛型集合、IDictionary 等类型
|
2025-07-26 19:36:54 +08:00
|
|
|
|
/// </summary>
|
2025-07-31 23:59:31 +08:00
|
|
|
|
public static Func<object, object, object> CreateCollectionGetter(Type collectionType, Type? itemType = null)
|
2025-07-26 19:36:54 +08:00
|
|
|
|
{
|
|
|
|
|
|
DynamicMethod dm = new DynamicMethod(
|
|
|
|
|
|
"GetCollectionValue",
|
|
|
|
|
|
typeof(object),
|
|
|
|
|
|
new[] { typeof(object), typeof(object) },
|
|
|
|
|
|
typeof(EmitHelper).Module,
|
2025-07-31 23:59:31 +08:00
|
|
|
|
skipVisibility: true);
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
|
|
|
|
|
ILGenerator il = dm.GetILGenerator();
|
|
|
|
|
|
|
2025-07-31 23:59:31 +08:00
|
|
|
|
// 数组类型处理
|
2025-07-26 19:36:54 +08:00
|
|
|
|
if (collectionType.IsArray)
|
|
|
|
|
|
{
|
|
|
|
|
|
var elementType = collectionType.GetElementType()!;
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, collectionType); // 转为真实数组类型
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
2025-07-31 23:59:31 +08:00
|
|
|
|
il.Emit(OpCodes.Unbox_Any, typeof(int)); // 转为int索引
|
2025-07-26 19:36:54 +08:00
|
|
|
|
il.Emit(OpCodes.Ldelem, elementType); // 取值
|
|
|
|
|
|
if (elementType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Box, elementType); // 装箱
|
2025-07-31 23:59:31 +08:00
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 非泛型 IDictionary 类型(如 Hashtable、JObject)
|
|
|
|
|
|
else if (IsGenericDictionaryType(collectionType, out var keyType, out var valueType))
|
|
|
|
|
|
{
|
|
|
|
|
|
var getItem = collectionType.GetMethod("get_Item", new[] { keyType });
|
|
|
|
|
|
if (getItem == null)
|
|
|
|
|
|
throw new NotSupportedException($"{collectionType} 未实现 get_Item({keyType})");
|
|
|
|
|
|
|
|
|
|
|
|
var returnType = getItem.ReturnType;
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, collectionType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
|
if (keyType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, keyType);
|
|
|
|
|
|
else
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, keyType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Callvirt, getItem);
|
|
|
|
|
|
|
|
|
|
|
|
if (returnType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Box, returnType);
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
}
|
2025-07-31 23:59:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 实现 get_Item 方法的类型(如 List<T>, Dictionary<TKey, TValue> 等)
|
2025-07-26 19:36:54 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-07-31 23:59:31 +08:00
|
|
|
|
/*var methodInfos = collectionType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
|
|
|
|
|
|
MethodInfo? getItem;
|
|
|
|
|
|
|
|
|
|
|
|
if (methodInfos.Length > 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
getItem = methodInfos.Where(m => m.Name.Equals("get_Item")).Where(m =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var ps = m.GetParameters().ToArray();
|
|
|
|
|
|
if (ps.Length > 1) return false;
|
|
|
|
|
|
if (ps[0].ParameterType == typeof(object)) return false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}).FirstOrDefault();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
//getItem = collectionType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);
|
|
|
|
|
|
getItem = methodInfos.First(m => m.Name.Equals("get_Item"));
|
|
|
|
|
|
}
|
|
|
|
|
|
*/
|
|
|
|
|
|
// GetMethod(name, bindingAttr, binder: null, types, modifiers: null);
|
|
|
|
|
|
MethodInfo? getItem = collectionType.GetMethod("get_Item", bindingAttr: BindingFlags.Instance | BindingFlags.Public, binder: null, types: [itemType], modifiers: null);
|
2025-07-26 19:36:54 +08:00
|
|
|
|
if (getItem == null)
|
|
|
|
|
|
throw new NotSupportedException($"类型 {collectionType} 不支持 get_Item。");
|
|
|
|
|
|
|
2025-07-31 23:59:31 +08:00
|
|
|
|
var indexParamType = getItem.GetParameters()[0].ParameterType;
|
2025-07-26 19:36:54 +08:00
|
|
|
|
var returnType = getItem.ReturnType;
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
|
il.Emit(OpCodes.Castclass, collectionType);
|
|
|
|
|
|
il.Emit(OpCodes.Ldarg_1);
|
2025-07-31 23:59:31 +08:00
|
|
|
|
|
|
|
|
|
|
if (indexParamType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Unbox_Any, indexParamType);
|
2025-07-26 19:36:54 +08:00
|
|
|
|
else
|
2025-07-31 23:59:31 +08:00
|
|
|
|
il.Emit(OpCodes.Castclass, indexParamType);
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Callvirt, getItem);
|
|
|
|
|
|
|
|
|
|
|
|
if (returnType.IsValueType)
|
|
|
|
|
|
il.Emit(OpCodes.Box, returnType);
|
|
|
|
|
|
|
|
|
|
|
|
il.Emit(OpCodes.Ret);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (Func<object, object, object>)dm.CreateDelegate(typeof(Func<object, object, object>));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-31 23:59:31 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static bool IsGenericDictionaryType(Type type, out Type keyType, out Type valueType)
|
|
|
|
|
|
{
|
|
|
|
|
|
keyType = null!;
|
|
|
|
|
|
valueType = null!;
|
|
|
|
|
|
|
|
|
|
|
|
var dictInterface = type
|
|
|
|
|
|
.GetInterfaces()
|
|
|
|
|
|
.FirstOrDefault(t =>
|
|
|
|
|
|
t.IsGenericType &&
|
|
|
|
|
|
t.GetGenericTypeDefinition() == typeof(IDictionary<,>));
|
|
|
|
|
|
|
|
|
|
|
|
if (dictInterface != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var args = dictInterface.GetGenericArguments();
|
|
|
|
|
|
keyType = args[0];
|
|
|
|
|
|
valueType = args[1];
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-07-26 19:36:54 +08:00
|
|
|
|
}
|
2024-10-10 10:45:53 +08:00
|
|
|
|
}
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
|
|
|
|
|
|