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. 在 sql server 中批量删除表

    通过查询系统表,可以批量获得 drop 语句,执行即可... select 'drop table '+name+';' from sys.tables

  2. 使用JS通过Web API执行批量操作,多个操作是一个事务!

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复235或者20161105可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  3. Android 矢量图详解

    官方文档 关于 Vector,在官方开发指南中介绍.本文章是由个人翻译官方指南然后添加个人理解完成. 由于个人精力有限,多个渠道发布,排版上可能会有问题,如果影响查看,请移步 Android 开发者家 ...

  4. HttpClient的使用今天遇到一个巨坑——HttpEntity内容取不出来

    在使用HttpPost httpPost = new HttpPost(postUrl);的post请求后,拿到返回的response,response返回200成功. 到此没有任何问题. respo ...

  5. SparkSql 整合 Hive

    SparkSql整合Hive 需要Hive的元数据,hive的元数据存储在Mysql里,sparkSql替换了yarn,不需要启动yarn,需要启动hdfs 首先你得有hive,然后你得有spark, ...

  6. CGROUP九大子系统

    blkio -- 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等等). cpu -- 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问. cpuacct ...

  7. emacs semantic,speedbar,gdb汇总

    在emacs 里使用gdb emacs speedbar功能介绍 semantic功能介绍 上面3篇文章精华,都汇总到下面的.emacs文件里了. ;;启动semantic功能 (semantic-m ...

  8. mybatis与hibernate的区别持久层对比【面试题】

    Mybatis技术特点: 好处: 通过直接编写SQL语句,可以直接对SQL进行性能的优化: 学习门槛低,学习成本低.只要有SQL基础,就可以学习mybatis,而且很容易上手: 由于直接编写SQL语句 ...

  9. day70_10_16drf组件响应模块,异常模块和序列化模块。

    一.解析模块 为什么要配置解析模块? 1)drf给我们通过了多种解析数据包方式的解析类. 2)我们可以通过配置来控制前台提交的哪些格式的数据后台在解析,哪些数据不解析. 3)全局配置就是针对每一个视图 ...

  10. VMWare虚拟机提示:另一个程序已锁定文件的一部分,打不开磁盘...模块"Disk"启动失败的解决办法

    重启了电脑之后,打开VMware就发现出现了“锁定文件失败,打不开磁盘......模块"Disk"启动失败.”这些文字 为什么会出现这种问题: 这是因为虚拟机在运行的时候,会锁定文 ...