zoukankan      html  css  js  c++  java
  • Expression表达式目录树动态拼接 反射获取泛型方法

        class TestOne
        {
    
            public String[] arr = { "1", "2", "3" };
    
            public class Student
            {
                public int Id { get; set; }
                public string Name { get; set; }
                public String Code { get; set; }
            }
    
            public Expression<Func<Student, bool>> Fun1()
            {
    
                Expression<Func<Student, bool>> customExpression = s => arr.Contains(s.Code);
    
                return customExpression;
    
            }       
    
        }
    

      上面我贴出了源码,如果要用 Expression动态拼接出  Expression<Func<Student, bool>> customExpression = s => arr.Contains(s.Code) ,该怎么弄。

    这里包含很多东西,访问类Student的属性Code,访问类TestOne的字段arr,然后就是arr调用Contains方法。

      选从简单的开始,选动态拼装 s.Code 直接上代码

                ParameterExpression parameterExpression = Expression.Parameter(typeof(Student), "s");
                MethodInfo codeMethod = typeof(Student).GetProperty("Code").GetMethod;
                MemberExpression memberExpression = Expression.Property(parameterExpression, codeMethod);
    

       s.Code 已经准备好了,然后开始拼装arr.Contains(),这里我们很容易会误以为Contains这个方法是String数组所拥有的方法。其实是错误的,直接F12查看方法定义,

    发现它是在静态类Enumerable里写的一个参数为IEnumerable<TSource> 的泛型扩展方法。所以

                MethodInfo[] methods = typeof(Enumerable).GetMethods();
                MethodInfo method1 = methods.FirstOrDefault(e => e.Name == "Contains" && e.GetParameters().Length == 2);
                //MethodInfo method1 = typeof(Enumerable).GetMethod("Contains", new Type[] { typeof(IEnumerable<>), null });
                MethodInfo method2 = method1.MakeGenericMethod(typeof(String));
    

    其中method1的获取还大费周折了一番。刚开始我直接用GetMethod方法直接获取到所需要的Contains方法的MethodInfo对象,但是在填写类型Type数组时,你会发现,第二个参数的类型你不知道怎么填写,因为它是一个泛型参数,所以你不知道它是什么类型(上面代码被注释的那一行代码)。为此,我上网这种搜,研究了一晚上,也没有破解。所以就采用第二种方案。用GetMethods获取所有MethodInfo对象,然后再筛选。

    完成了关键步骤,就好办了,贴出全部代码

            public Expression<Func<Student, bool>> Fun2()
            {
    
                ParameterExpression parameterExpression = Expression.Parameter(typeof(Student), "s");
                MethodInfo codeMethod = typeof(Student).GetProperty("Code").GetMethod;
                MemberExpression memberExpression = Expression.Property(parameterExpression, codeMethod);
    
                FieldInfo filed = typeof(TestOne).GetField("arr");
                MemberExpression filedExpression = Expression.Field(Expression.Constant(this, typeof(TestOne)), filed);
    
    
                MethodInfo[] methods = typeof(Enumerable).GetMethods();
                MethodInfo method1 = methods.FirstOrDefault(e => e.Name == "Contains" && e.GetParameters().Length == 2);
                //MethodInfo method1 = typeof(Enumerable).GetMethod("Contains", new Type[] { typeof(IEnumerable<>), null });
                MethodInfo method2 = method1.MakeGenericMethod(typeof(String));         
    
                MethodCallExpression callExpression = Expression.Call(null, method2, new Expression[]
                {
                    filedExpression,
                    memberExpression,
                });
    
                Expression<Func<Student, bool>> customExpression = Expression.Lambda<Func<Student, bool>>
                    (callExpression, new ParameterExpression[] { parameterExpression });
    
                return customExpression;
            }
    

      

    对于我上面提到的一个问题就是 用GetMethod方法 直接获取到Contains方法的MethodInfo对象。这个是从理论上就实现不了(因为是泛型,再没有调用之前是不知道类型的),还是说微软框架就没有提供这种直接获取到泛型参数的MethodInfo对象的实现。有了解的朋友欢迎留言指点讨论。

  • 相关阅读:
    css3新特性总结
    ES6常用特性总览
    前端第一次面试
    将一个行数在主线程执行的4中方法
    判断邮箱格式和图片压缩
    上传图片的实现
    导航右侧添加按钮、隐藏导航条和状态栏
    从相册选取图片展示并实现自定义事件
    cell添加选中时的背景图片、显示图片和图片自适应框的大小
    设置键盘无色和状态栏风火轮、屏幕截图
  • 原文地址:https://www.cnblogs.com/xiaoZhang521/p/11374258.html
Copyright © 2011-2022 走看看