Net Core 一个简单的封装,缓存表达式树去生成反射的调用
namespace LuciusLiang.Common { /// <summary> /// 自定义表达式构建 /// </summary> public class CustomExpressionBuilder { /// <summary> /// 内置缓存 /// </summary> private static IMemoryCache _memoryCache = new MemoryCache(new MemoryCacheOptions()); /// <summary> /// 构建获取 TAttributeType 特性委托 /// </summary> /// <typeparam name="TAttributeType">需要获取的 Attribute 类型</typeparam> /// <returns></returns> public static Func<MemberInfo, TAttributeType> BuildGetAttribute<TAttributeType>() where TAttributeType : Attribute { var cacheName = "GetAttribute_" + typeof(TAttributeType).Name; if (_memoryCache.TryGetValue(cacheName, out Func<MemberInfo, TAttributeType> funcCallMethod)) { return funcCallMethod; } var methodInfo = typeof(CustomAttributeExtensions).GetMethod(nameof(CustomAttributeExtensions.GetCustomAttribute), new[] { typeof(MemberInfo) }); funcCallMethod = BuildCallStaticMethod<Func<MemberInfo, TAttributeType>>(methodInfo, new Type[] { typeof(TAttributeType) }); _memoryCache.Set(cacheName, funcCallMethod); return funcCallMethod; } /// <summary> /// 构建调用泛型函数委托 /// </summary> /// <typeparam name="TCallMethodDelegateType">构建的委托类型</typeparam> /// <param name="methodInfo">调用的方法 MethodInfo</param> /// <param name="genericMethodArgments">泛型函数参数</param> /// <returns></returns> public static TCallMethodDelegateType BuildCallStaticMethod<TCallMethodDelegateType>(MethodInfo methodInfo, Type[] genericMethodArgments = null) where TCallMethodDelegateType : Delegate { var cacheName = $"{ methodInfo.DeclaringType.Name }_StaticMethod_{ methodInfo.Name }"; if (_memoryCache.TryGetValue(cacheName, out TCallMethodDelegateType funcCallMethod)) { return funcCallMethod; } if (methodInfo.IsGenericMethod) { methodInfo = methodInfo.MakeGenericMethod(genericMethodArgments); } var methodParamsExpression = methodInfo.GetParameters().Select(t => { return Expression.Parameter(t.ParameterType, t.Name); }).ToList(); var methodCallExpression = Expression.Call(methodInfo, methodParamsExpression); funcCallMethod = Expression.Lambda<TCallMethodDelegateType>(methodCallExpression, methodParamsExpression).Compile(); _memoryCache.Set(cacheName, funcCallMethod); return funcCallMethod; } /// <summary> /// 构建目标类型的函数调用委托 /// 委托参数顺序: /// <para>第一个(必须): TSource 类型 </para> /// <para>第二个(可选,可多个,如果函数没有参数就没有):调用函数型数类型 </para> /// <para>最后一个是返回参数类型:(可选,如果返回为Void)</para> /// </summary> /// <typeparam name="TSource">调用函数的所属类类型</typeparam> /// <typeparam name="TCallMethodDelegateType">生成的委托类型</typeparam> /// <param name="methodInfo">调用的函数 MethodInfo 信息</param> /// <returns></returns> public static TCallMethodDelegateType BuildTypeCallMethod<TSource, TCallMethodDelegateType>(MethodInfo methodInfo) where TCallMethodDelegateType : Delegate where TSource : class { var cacheName = $"{typeof(TSource).Name}_Method_{methodInfo.Name}"; if (_memoryCache.TryGetValue(cacheName, out TCallMethodDelegateType funcCallMethod)) { return funcCallMethod; } var sourceTypeExpression = Expression.Parameter(typeof(TSource), typeof(TSource).Name); var methodParamsExpression = methodInfo.GetParameters().Select(t => { return Expression.Parameter(t.ParameterType, t.Name); }).ToList(); var methodCallExpression = Expression.Call(sourceTypeExpression, methodInfo, methodParamsExpression); // 将实例类型插入到第一个位置 methodParamsExpression.Insert(0, sourceTypeExpression); funcCallMethod = Expression.Lambda<TCallMethodDelegateType>(methodCallExpression, methodParamsExpression).Compile(); _memoryCache.Set(cacheName, funcCallMethod); return funcCallMethod; } /// <summary> /// 构建 GetProperty 的委托 /// </summary> /// <typeparam name="TSource">属性所属类类型</typeparam> /// <typeparam name="TPropertyType">属性类型</typeparam> /// <param name="propertyName">属性名称</param> /// <returns></returns> public static Func<TSource, TPropertyType> BuildGetProperty<TSource, TPropertyType>(string propertyName) where TSource : class { var cacheName = $"{typeof(TSource).Name}_GetProperty_{propertyName}"; if (_memoryCache.TryGetValue(cacheName, out Func<TSource, TPropertyType> funcGetProperty)) { return funcGetProperty; } var sourceTypeExpression = Expression.Parameter(typeof(TSource)); var getPropertyExpression = Expression.Property(sourceTypeExpression, propertyName); funcGetProperty = Expression.Lambda<Func<TSource, TPropertyType>>(getPropertyExpression, sourceTypeExpression).Compile(); _memoryCache.Set(cacheName, funcGetProperty); return funcGetProperty; } /// <summary> /// 构建 SetProperty 的委托 /// </summary> /// <typeparam name="TSource">属性所属类类型</typeparam> /// <typeparam name="TPropertyType">属性类型</typeparam> /// <param name="propertyName">属性名称</param> /// <returns></returns> public static Action<TSource, TPropertyType> BuildSetProperty<TSource, TPropertyType>(string propertyName) where TSource : class { var cacheName = $"{typeof(TSource).Name}_SetProperty_{propertyName}"; if (_memoryCache.TryGetValue(cacheName, out Action<TSource, TPropertyType> actionSetMethod)) { return actionSetMethod; } var methodInfo = typeof(TSource).GetProperty(propertyName).SetMethod; actionSetMethod = BuildTypeCallMethod<TSource, Action<TSource, TPropertyType>>(methodInfo); _memoryCache.Set(cacheName, actionSetMethod); return actionSetMethod; } } }