• 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;
            }
    
        }
    }
  • 相关阅读:
    《团队-Android手机便签-项目进度》
    《结对-结对编项目作业名称-测试过程》
    《结对-结对编项目作业名称-开发过程》
    ios auto layout demystified (二)
    ios auto layout demystified (一)
    电子书下载地址
    轻应用、Web app 、Native app三者区别关系是什么?
    ios录制测试
    Understanding apps: mobile, native or responsive
    iOS开发工具——网络封包分析工具Charles
  • 原文地址:https://www.cnblogs.com/luciusliang/p/14364625.html
Copyright © 2020-2023  润新知