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 ...
随机推荐
- HTTP中的2XX状态码
HTTP状态码分类 1XX --信息,服务器收到请求,需要请求者继续执行操作 2XX--成功,操作被成功接收并处理 3XX--重定向,需要进一步的操作以完成请求 4XX--客户端错误,请求包含语法错误 ...
- Android多module下重复jar包问题
版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/166 Android多module下重复jar包问题 An ...
- linux 创建虚拟块设备,制作文件系统并挂载,用于测试lustre
1.制作块文件 3 个 [root@localhost yaoxu]# [root@localhost yaoxu]# [root@localhost yaoxu]# 2.创建回环设备 [root@l ...
- 在emacs 里使用gdb
在emacs 里使用gdb M-x gdb就在emacs里启动了gdb 在gdb窗口里shell-mode的命令都适用 启动gdb后,再启动minor mode:M-x gud-tooltip-mod ...
- -bash: /home/java/jdk1.8.0_221/bin/java: 权限不够
1)进入存放jdk文件的文件夹路径我这里是 usr/local/jdk/2)输入命令 chmod 777 jdk1.8.0_221/bin/java修改权限3)再次输入 java -version 成 ...
- Linux:目录的查找
搜索文件与目录 find [查找范围] [查找条件表达式] 常用的选项 -name 按名称查找,允许使用通配符 -type 按文件类型查找 文件类型包括: 普通文件 f 目录 d 块设备文件 b 字符 ...
- python语法区别
python语法区别: 大小写敏感 (动态语言:python)变量不用声明 p.s: 静态语言(Java)必须声明变量 语句末尾可以不打分号 可以直接进行数学计算 复制.粘贴功能失效,粘贴到别的地方的 ...
- 【转】认识JWT
1. JSON Web Token是什么 JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的.自包含的方式,用于作为JSON对象在各方之间安全地传输信息.该 ...
- Octave教程
Windows安装Octave http://wiki.octave.org/Octave_for_Microsoft_Windows 基本操作(Basic Operations) octave:1& ...
- remote: http basic: access denied fatal: authentication failed for '‘解决办法
问题描述 由于这个项目代码使用https 进行clone,为什么?因为代码库ssh有问题!fuck! 导致在push代码的时候出现了 remote: http basic: access denied ...