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对象的实现。有了解的朋友欢迎留言指点讨论。
Expression表达式目录树动态拼接 反射获取泛型方法的更多相关文章
- 第十五节:Expression表达式目录树(与委托的区别、自行拼接、总结几类实例间的拷贝)
一. 基本介绍 回忆: 最早接触到表达式目录树(Expression)可能要追溯到几年前使用EF早期的时候,发现where方法里的参数是Expression<Func<T,bool> ...
- 【学习笔记】Expression表达式目录树
Expression表达式目录树:一个能拼装能解析的数据结构,语法树. 一.手动拼装表达式目录树 示例1: /// <summary> /// 展示表达式树,协助用的 /// 编译lamb ...
- Expression表达式目录树
一.初识Expression 1.在上一篇我们讲到了委托(忘记了可以在看看,点赞在看养成习惯),今天要讲的Expression也和委托有一点点关系吧(没有直接关系,只是想要大家看看我其他的文章),Ex ...
- 【手撸一个ORM】第五步、Expression(表达式目录树)转换为Where子句
说明 在SQL中,查询.修改比较常用到WHERE子句,在这里根据使用场景不同,定义了两个类,一个用于查询,一个用于修改(插入)操作.原因是: 查询操作支持一级导航属性查询,如student.Schoo ...
- EXpression 表达式目录树
表达式树 前面n-1的是一个表达式 最后一个是一个表达式 一直拆开拆到最后 继承ExpressionVisitor的类 可以重写获取到表达式树的方法进行扩张和改写 委托是编译成一个方法 表达 ...
- 学习笔记: Expression表达式目录树详解和扩展封装
1. 表达式链接扩展封装,ORM常用 And Or /// <summary> /// 表达式访问者 /// </summary> public class Expressi ...
- 表达式目录树(Expression)
一:什么是表达式树 Expression我们称为是表达式树,是一种数据结构体,用于存储需要计算,运算的一种结构,这种结构可以只是存储,而不进行运算.通常表达式目录树是配合Lambda一起来使用的,la ...
- C#表达式目录树(Expression)
1.什么是表达式目录树 :简单的说是一种语法树,或者说是一种数据结构(Expression) 2.用Lambda声明表达式目录树: Expression<Func<; //表达试目录树的方 ...
- C#简单实现表达式目录树(Expression)
1.什么是表达式目录树 :简单的说是一种语法树,或者说是一种数据结构(Expression) 2.用Lambda声明表达式目录树: 1 2 3 4 5 Expression<Func<in ...
随机推荐
- Tasteless challenges medium WP
http://chall.tasteless.eu/ 国外的一个靶场,都是单点知识,medium大部分还是比较简单 medium Level 1- Infiltration http://chall. ...
- Python目录和文件处理总结
1.判断目录是否存在.判断文件是否存在.创建目录.重命名目录或文件 import os #获取当前目录路径: E:\Work\Projects\python print(os.getcwd()) #判 ...
- python从入门到放弃之线程篇
一,什么是多线程? 1.多线程的概念? 说起多线程,那么就不得不说什么是线程,而说起线程,又不得不说什么是进程. 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分 ...
- 微信小程序如何使用 Git 实现版本管理和协作开发
前言 在微信小程序开发的过程中,代码版本管理往往需要使用第三方工具进行管理.虽然微信Web开发工具提供了对Git文件版本状态的提示,但实际的使用体验依然不尽人意. 随着微信Web开发工具的更新,最新的 ...
- 《大话处理器》Cache一致性协议之MESI【转】
转自:https://blog.csdn.net/muxiqingyang/article/details/6615199 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载 ...
- Linux:路径的概念及路径的切换
路径分为绝对路径和相对路径 绝对路径:从/根开头的路径为绝对路径 相对路径:以当前目录为开头的为相对路径 根目录:/ 家目录:普通用户的家目录在/home下,root用户的家目录是/root 切换目录 ...
- C学习笔记(9)--- 预处理器,头文件
1.预处理器: 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤.简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理. 我们将把 C 预处理 ...
- XML配置报错
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springfram ...
- 实例透彻分析CMS垃圾收集器执行过程
CMS收集器收集步骤: 在上一次[https://www.cnblogs.com/webor2006/p/11055468.html]中已经对CMS的垃圾收集器有了一定的理论上的了解,其中提到了CMS ...
- 8.gitlab 邮件设置
这个我没做实验. 视屏里面说的 126的 邮箱限制少点. 建议用126的 邮箱. 参考视屏 jenkins+gitlab+插件\1\7(07-gitlab备份恢复) 最后的一点部分. 需要在配 ...