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对象的实现。有了解的朋友欢迎留言指点讨论。

Expression表达式目录树动态拼接 反射获取泛型方法的更多相关文章

  1. 第十五节:Expression表达式目录树(与委托的区别、自行拼接、总结几类实例间的拷贝)

    一. 基本介绍 回忆: 最早接触到表达式目录树(Expression)可能要追溯到几年前使用EF早期的时候,发现where方法里的参数是Expression<Func<T,bool> ...

  2. 【学习笔记】Expression表达式目录树

    Expression表达式目录树:一个能拼装能解析的数据结构,语法树. 一.手动拼装表达式目录树 示例1: /// <summary> /// 展示表达式树,协助用的 /// 编译lamb ...

  3. Expression表达式目录树

    一.初识Expression 1.在上一篇我们讲到了委托(忘记了可以在看看,点赞在看养成习惯),今天要讲的Expression也和委托有一点点关系吧(没有直接关系,只是想要大家看看我其他的文章),Ex ...

  4. 【手撸一个ORM】第五步、Expression(表达式目录树)转换为Where子句

    说明 在SQL中,查询.修改比较常用到WHERE子句,在这里根据使用场景不同,定义了两个类,一个用于查询,一个用于修改(插入)操作.原因是: 查询操作支持一级导航属性查询,如student.Schoo ...

  5. EXpression 表达式目录树

    表达式树   前面n-1的是一个表达式  最后一个是一个表达式  一直拆开拆到最后 继承ExpressionVisitor的类  可以重写获取到表达式树的方法进行扩张和改写 委托是编译成一个方法 表达 ...

  6. 学习笔记: Expression表达式目录树详解和扩展封装

    1. 表达式链接扩展封装,ORM常用 And  Or /// <summary> /// 表达式访问者 /// </summary> public class Expressi ...

  7. 表达式目录树(Expression)

    一:什么是表达式树 Expression我们称为是表达式树,是一种数据结构体,用于存储需要计算,运算的一种结构,这种结构可以只是存储,而不进行运算.通常表达式目录树是配合Lambda一起来使用的,la ...

  8. C#表达式目录树(Expression)

    1.什么是表达式目录树 :简单的说是一种语法树,或者说是一种数据结构(Expression) 2.用Lambda声明表达式目录树: Expression<Func<; //表达试目录树的方 ...

  9. C#简单实现表达式目录树(Expression)

    1.什么是表达式目录树 :简单的说是一种语法树,或者说是一种数据结构(Expression) 2.用Lambda声明表达式目录树: 1 2 3 4 5 Expression<Func<in ...

随机推荐

  1. kali linux maltego-情报收集工具

    Maltego是一个交互式数据挖掘工具,它为链接分析呈现有向图.该工具用于在线调查,以发现互联网上各种来源的信息片段之间的关系. 注册Maltego账号,注册地址:https://www.paterv ...

  2. 【JavaWeb】Ajax基础

    Ajax介绍 Asynchronous JavaScript And XML(异步的JavaScript和XML): Ajax可以在不刷新页面的前提下,进行页面局部更新: Ajax不是新的技术,Aja ...

  3. 026.[转] 基于Docker及Kubernetes技术构建容器云平台 (PaaS)

    [编者的话] 目前很多的容器云平台通过Docker及Kubernetes等技术提供应用运行平台,从而实现运维自动化,快速部署应用.弹性伸缩和动态调整应用环境资源,提高研发运营效率. 本文简要介绍了与容 ...

  4. Java并发编程艺术读书笔记

    1.多线程在CPU切换过程中,由于需要保存线程之前状态和加载新线程状态,成为上下文切换,上下文切换会造成消耗系统内存.所以,可合理控制线程数量. 如何控制: (1)使用ps -ef|grep appn ...

  5. 8.JavaCC官方入门指南-例3

    例3:计算器-double类型加法   下面我们对上个例子的代码进行进一步的修改,使得代码具有简单的四则运算的功能.   第一步修改,我们将打印出每一行的值,使得计算器更具交互性.一开始,我们只是把数 ...

  6. 自动化部署-svn hook触发构建

    目的 之前是通过轮询的形式,2分钟更新一次svn,即时性不高,现在想要实现提交代码时直接触发构建 方案 使用svn的服务器hook,当有代码提交时请求jenkins api实现构建 具体实现 1.je ...

  7. 23.Java基础_ArrayList类

    ArrayList类的构造和使用方法 import java.util.ArrayList; public class test { public static void main(String[] ...

  8. 4. Go语言—值类型和引用类型

    一.值类型 1. 定义 ​ 变量直接存储的值,内存通常在栈中分配: var i = 5 -> i-->5 2. 应用 int.float.bool.string.数组.struct 二.引 ...

  9. Redis学习笔记(八、缓存设计)

    目录: 缓存更新策略 缓存粒度 缓存穿透 缓存雪崩 缓存击穿 缓存更新策略: 1.内存溢出淘汰策略 当redis的使用内存超过maxmemory时会触发相应的策略,具体策略由maxmemory-pol ...

  10. 好用的代码统计小工具SourceCounter(下载)

    SourceCounter下载链接 https://pan.baidu.com/s/12Cg51L0hRn5w-m1NQJ-Xlg 提取码:i1cd 很多时候我们需要统计自己所写的代码的数量.举个栗子 ...