Files
serein-flow/Library/Utils/ExpressionHelper.cs
fengjiayi 152077e9b5 1. 重新设计了Generate项目及相关特性的命名,避免与其他类型混淆。
2. 补充了部分注释。
3. 修改了删除容器节点时,容器内子节点未正确删除的问题。
2025-07-30 21:15:07 +08:00

433 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Serein.Library.Api;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
namespace Serein.Library.Utils
{
/// <summary>
/// 基于类型创建表达式树反射委托目前已使用EmitHelper代替
/// </summary>
public static class ExpressionHelper
{
/// <summary>
/// 缓存表达式树反射方法
/// </summary>
private static ConcurrentDictionary<string, Delegate> Cache { get; } = new ConcurrentDictionary<string, Delegate>();
#region
#region
/// <summary>
/// 动态获取属性值
/// </summary>
public static Delegate PropertyGetter(Type type, string propertyName)
{
string cacheKey = $"{type.FullName}.{propertyName}.Getter";
return Cache.GetOrAdd(cacheKey, _ => CreateGetterDelegate(type, propertyName));
}
/// <summary>
/// 动态获取属性值
/// </summary>
private static Delegate CreateGetterDelegate(Type type, string propertyName)
{
var parameter = Expression.Parameter(typeof(object), "instance");
var property = Expression.Property(Expression.Convert(parameter, type), propertyName);
var lambda = Expression.Lambda(Expression.Convert(property, typeof(object)), parameter);
return lambda.Compile();
}
/// <summary>
/// 动态设置属性值
/// </summary>
public static Delegate PropertySetter(Type type, string propertyName)
{
string cacheKey = $"{type.FullName}.{propertyName}.Setter";
return Cache.GetOrAdd(cacheKey, _ => CreateSetterDelegate(type, propertyName));
}
/// <summary>
/// 动态设置属性值
/// </summary>
private static Delegate CreateSetterDelegate(Type type, string propertyName)
{
var parameter = Expression.Parameter(typeof(object), "instance");
var value = Expression.Parameter(typeof(object), "value");
var property = Expression.Property(Expression.Convert(parameter, type), propertyName);
var assign = Expression.Assign(property, Expression.Convert(value, property.Type));
var lambda = Expression.Lambda(assign, parameter, value);
return lambda.Compile();
}
/// <summary>
/// 动态获取字段值
/// </summary>
public static Delegate FieldGetter(Type type, string fieldName)
{
string cacheKey = $"{type.FullName}.{fieldName}.FieldGetter";
return Cache.GetOrAdd(cacheKey, _ => CreateFieldGetterDelegate(type, fieldName));
}
/// <summary>
/// 动态获取字段值
/// </summary>
private static Delegate CreateFieldGetterDelegate(Type type, string fieldName)
{
var parameter = Expression.Parameter(typeof(object), "instance");
var field = Expression.Field(Expression.Convert(parameter, type), fieldName);
var lambda = Expression.Lambda(Expression.Convert(field, typeof(object)), parameter);
return lambda.Compile();
}
/// <summary>
/// 动态设置字段值
/// </summary>
public static Delegate FieldSetter(Type type, string fieldName)
{
string cacheKey = $"{type.FullName}.{fieldName}.FieldSetter";
return Cache.GetOrAdd(cacheKey, _ => CreateFieldSetterDelegate(type, fieldName));
}
/// <summary>
/// 动态设置字段值
/// </summary>
private static Delegate CreateFieldSetterDelegate(Type type, string fieldName)
{
var parameter = Expression.Parameter(typeof(object), "instance");
var value = Expression.Parameter(typeof(object), "value");
var field = Expression.Field(Expression.Convert(parameter, type), fieldName);
var assign = Expression.Assign(field, Expression.Convert(value, field.Type));
var lambda = Expression.Lambda(assign, parameter, value);
return lambda.Compile();
}
#endregion
/// <summary>
/// 表达式树构建无参数,无返回值方法
/// </summary>
public static Delegate MethodCaller(Type type, MethodInfo methodInfo)
{
string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCaller";
return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(type, methodInfo));
}
/// <summary>
/// 表达式树构建无参数,无返回值方法
/// </summary>
private static Delegate CreateMethodCallerDelegate(Type type, MethodInfo methodInfo)
{
var parameter = Expression.Parameter(typeof(object), "instance");
var methodCall = Expression.Call(Expression.Convert(parameter, type), methodInfo);
var lambda = Expression.Lambda(methodCall, parameter);
// Action<object>
return lambda.Compile();
}
/// <summary>
/// 表达式树构建无参数,有返回值方法
/// </summary>
public static Delegate MethodCallerHaveResult(Type type, MethodInfo methodInfo)
{
string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCallerHaveResult";
return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateHaveResult(type, methodInfo));
}
/// <summary>
/// 表达式树构建无参数,有返回值方法
/// </summary>
private static Delegate CreateMethodCallerDelegateHaveResult(Type type, MethodInfo methodInfo)
{
var parameter = Expression.Parameter(typeof(object), "instance");
var methodCall = Expression.Call(Expression.Convert(parameter, type), methodInfo);
if (EmitHelper.IsGenericTask(methodInfo.ReturnType, out var taskResult))
{
if (taskResult is null)
{
var lambda = Expression.Lambda<Func<object, Task>>(Expression.Convert(methodCall, typeof(Task)), parameter);
return lambda.Compile();
}
else
{
var lambda = Expression.Lambda<Func<object, Task<object>>>(Expression.Convert(methodCall, typeof(Task<object>)), parameter);
return lambda.Compile();
}
}
else
{
var lambda = Expression.Lambda<Func<object, object>>(Expression.Convert(methodCall, typeof(object)), parameter);
return lambda.Compile();
}
}
/// <summary>
/// 表达式树构建多个参数,无返回值的方法
/// </summary>
public static Delegate MethodCaller(Type type, MethodInfo methodInfo, params Type[] parameterTypes)
{
string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCaller";
return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegate(type, methodInfo, parameterTypes));
}
/// <summary>
/// 表达式树构建多个参数,无返回值的方法
/// </summary>
private static Delegate CreateMethodCallerDelegate(Type type, MethodInfo methodInfo, Type[] parameterTypes)
{
/* var parameter = Expression.Parameter(typeof(object), "instance");
var arguments = parameterTypes.Select((t, i) => Expression.Parameter(typeof(object), $"arg{i}")).ToArray();
var convertedArguments = arguments.Select((arg, i) => Expression.Convert(arg, parameterTypes[i])).ToArray();
var methodCall = Expression.Call(Expression.Convert(parameter, type),
methodInfo,
convertedArguments);
var lambda = Expression.Lambda(methodCall, new[] { parameter }.Concat(arguments));
var tmpAction = lambda.Compile();
// Action<object, object[]>
return lambda.Compile();*/
var instanceParam = Expression.Parameter(typeof(object), "instance");
var argsParam = Expression.Parameter(typeof(object[]), "args");
// 创建参数表达式
var convertedArgs = parameterTypes.Select((paramType, index) =>
Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)), paramType)
).ToArray();
// 创建方法调用表达式
var methodCall = Expression.Call(
Expression.Convert(instanceParam, type),
methodInfo,
convertedArgs
);
// 创建 lambda 表达式
var lambda = Expression.Lambda(
methodCall,
instanceParam,
argsParam
);
// Func<object, object[], object>
return lambda.Compile();
}
/// <summary>
/// 表达式树构建多个参数,有返回值的方法
/// </summary>
public static Delegate MethodCallerHaveResult(Type type, MethodInfo methodInfo, Type[] parameterTypes)
{
string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCallerHaveResult";
return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateHaveResult(type, methodInfo, parameterTypes));
}
/// <summary>
/// 表达式树构建多个参数,有返回值的方法
/// </summary>
private static Delegate CreateMethodCallerDelegateHaveResult(Type type, MethodInfo methodInfo, Type[] parameterTypes)
{
/*var instanceParam = Expression.Parameter(typeof(object), "instance");
var argsParam = Expression.Parameter(typeof(object[]), "args");
// 创建参数表达式
var convertedArgs = parameterTypes.Select((paramType, index) =>
Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)), paramType)
).ToArray();
// 创建方法调用表达式
var methodCall = Expression.Call(
Expression.Convert(instanceParam, type),
methodInfo,
convertedArgs
);
// 创建 lambda 表达式
var lambda = Expression.Lambda(
Expression.Convert(methodCall, typeof(object)),
instanceParam,
argsParam
);
// Func<object, object[], object>
return lambda.Compile();*/
var instanceParam = Expression.Parameter(typeof(object), "instance");
var argsParam = Expression.Parameter(typeof(object[]), "args");
// 创建参数表达式
var convertedArgs = parameterTypes.Select((paramType, index) =>
Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)), paramType)
).ToArray();
// 创建方法调用表达式
var methodCall = Expression.Call(
Expression.Convert(instanceParam, type),
methodInfo,
convertedArgs
);
if (EmitHelper.IsGenericTask(methodInfo.ReturnType, out var taskResult))
{
if (taskResult is null)
{
var lambda = Expression.Lambda<Func<object, object[], Task>>
(Expression.Convert(methodCall, typeof(Task)), instanceParam, argsParam);
return lambda.Compile();
}
else
{
var lambda = Expression.Lambda<Func<object, object[], Task<object>>>
(Expression.Convert(methodCall, typeof(Task<object>)), instanceParam, argsParam);
return lambda.Compile();
}
}
else
{
var lambda = Expression.Lambda<Func<object, object[], object>>
(Expression.Convert(methodCall, typeof(object)), instanceParam, argsParam);
return lambda.Compile();
}
}
/// <summary>
/// 表达式树构建无参数,有返回值(Task&lt;object&gt;)的方法(触发器)
/// </summary>
public static Delegate MethodCallerAsync(Type type, MethodInfo methodInfo)
{
string cacheKey = $"{type.FullName}.{methodInfo.Name}.MethodCallerAsync";
return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateAsync(type, methodInfo));
}
/// <summary>
/// 表达式树构建无参数,有返回值(Task&lt;object&gt;)的方法(触发器)
/// </summary>
/// <param name="type"></param>
/// <param name="methodInfo"></param>
/// <returns></returns>
private static Delegate CreateMethodCallerDelegateAsync(Type type, MethodInfo methodInfo)
{
var parameter = Expression.Parameter(typeof(object), "instance");
var methodCall = Expression.Call(Expression.Convert(parameter, type), methodInfo);
var lambda = Expression.Lambda<Func<object, Task<object>>>(
Expression.Convert(methodCall, typeof(Task<object>)), parameter);
// Func<object, Task<object>>
return lambda.Compile();
}
/// <summary>
/// 表达式树构建多个参数,有返回值(Task&lt;object&gt;)的方法(触发器)
/// </summary>
public static Delegate MethodCallerAsync(Type type, MethodInfo method, params Type[] parameterTypes)
{
string cacheKey = $"{type.FullName}.{method.Name}.MethodCallerAsync";
return Cache.GetOrAdd(cacheKey, _ => CreateMethodCallerDelegateAsync(type, method, parameterTypes));
}
/// <summary>
/// 表达式树构建多个参数,有返回值(Task&lt;object&gt;)的方法(触发器)
/// </summary>
private static Delegate CreateMethodCallerDelegateAsync(Type type, MethodInfo methodInfo, Type[] parameterTypes)
{
var instanceParam = Expression.Parameter(typeof(object), "instance");
var argsParam = Expression.Parameter(typeof(object[]), "args");
// 创建参数表达式
var convertedArgs = parameterTypes.Select((paramType, index) =>
Expression.Convert(Expression.ArrayIndex(argsParam, Expression.Constant(index)), paramType)
).ToArray();
// 创建方法调用表达式
var methodCall = Expression.Call(
Expression.Convert(instanceParam, type),
methodInfo,
convertedArgs
);
// 创建 lambda 表达式
var lambda = Expression.Lambda<Func<object, object[], Task<IFlipflopContext<object>>>>(
Expression.Convert(methodCall, typeof(Task<IFlipflopContext<object>>)),
instanceParam,
argsParam
);
//获取返回类型
//var returnType = methodInfo.ReturnType;
//var lambda = Expression.Lambda(
// typeof(Func<,,>).MakeGenericType(typeof(object), typeof(object[]), returnType),
// Expression.Convert(methodCall, returnType),
// instanceParam,
// argsParam
// );
//var resule = task.DynamicInvoke((object)[Activator.CreateInstance(type), [new DynamicContext(null)]]);
return lambda.Compile();
}
/// <summary>
/// / 自动创建一个委托,根据方法信息和类型
/// </summary>
/// <param name="type"></param>
/// <param name="methodInfo"></param>
/// <returns></returns>
public static Delegate AutoCreate(Type type, MethodInfo methodInfo)
{
Type returnType = methodInfo.ReturnType;
var parameterTypes = methodInfo.GetParameters().Select(p => p.ParameterType).ToArray();
var parameterCount = parameterTypes.Length;
if (returnType == typeof(void))
{
if (parameterCount == 0)
{
// 无返回值,无参数
return MethodCaller(type, methodInfo);
}
else
{
// 无返回值,有参数
return MethodCaller(type, methodInfo, parameterTypes);
}
}
else
{
if (parameterCount == 0)
{
// 有返回值,无参数
return MethodCallerHaveResult(type, methodInfo);
}
else
{
// 有返回值,有参数
return MethodCallerHaveResult(type, methodInfo, parameterTypes);
}
}
#endregion
}
}
}