Linq之Expression高级篇(常用表达式类型)
首先回顾一下上篇文章的内容,上篇文章介绍了表达式树的解析和编译。如果忘记了,可以通过下面系列文章提供的入口进行复习。这篇文章将介绍常见的表达式类型。
常见的表达式类型都有个共同的基类Expression。创建这些类型的对象,是通过API的方式创建的(也就是Expression的静态方法),首先引入命名空间:
1 using System.Linq.Expressions;变量表达式
在表达式树中使用ParameterExpression或者ParameterExpression表达式表示变量类型,下面看一个例子,我们定义一个int类型的变量i:
// ParameterExpression表示命名的参数表达式。 ParameterExpression i = Expression.Parameter(typeof(int),"i");
或者使用
1 ParameterExpression j = Expression.Variable(typeof(int), "j");
通过f12转到定义,发现这两个方法的注释几乎是一样的。静态方法Parameter第一个参数:定义的参数类型,第二个参数:为参数名称。
常量表达式在表达式树中使用ConstantExpression表达式表示具有常量值的表达式。,看一个例子,我们定义一个int类型的常量5.并将该值赋值给上面定义的变量i
![复制代码](http://common.cnblogs.com/images/copycode.gif)
1 // ParameterExpression表示命名的参数表达式。 2 ParameterExpression i = Expression.Parameter(typeof(int), "i"); 3 //ParameterExpression j = Expression.Variable(typeof(int), "j"); 4 ConstantExpression constExpr = Expression.Constant(5, typeof(int)); 5 // 创建一个表示赋值运算的 System.Linq.Expressions.BinaryExpression 6 //表示包含二元运算符的表达式。 7 BinaryExpression binaryExpression = Expression.Assign(i, constExpr);
![复制代码](http://common.cnblogs.com/images/copycode.gif)
Constrant方法第一个参数:常量,第二个参数为什么类型的常量。
这里提到了BinaryExpression表达式,该表达式标识包含二元运算符的表达式,类似与=, 这样的二元表达式都可以使用BinaryExpression表达式来表示。
调试模式下,在自动窗口查看当前表达式的DebugView属性,这个属性在调试表达式树的时候是非常有用的:
变量:
常量:
二元表达式:
通过观察上面的图,可知变量调试模式下DebugView属性将显示前面带有“$”符号的 ParameterExpression 变量名称。那么如果参数没有名称,则会为其分配一个自动生成的名称,例如 $var1 或 $var2(这里不再举例)。
条件表达式在很多时候,我们都需要使用条件表达式来过滤一些数据,然后返回满足条件的数据,在表达式中有这样一些表达式满足你的需求。
常见运算符
, =
, =
if....then:如果满足条件那么..
if...then...else:如果满足条件执行某某代码,否则执行另外的逻辑
一个例子
IfThenElse方法
1 public static ConditionalExpression IfThenElse( 2 Expression test, 3 Expression ifTrue, 4 Expression ifFalse 5 )
![复制代码](http://common.cnblogs.com/images/copycode.gif)
1 bool test = true; 2 ConditionalExpression codition = Expression.IfThenElse( 3 //条件 4 Expression.Constant(test), 5 //如果条件为true,调用WriteLine方法输出“条件为true” 6 Expression.Call( 7 null, 8 typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), 9 Expression.Constant("条件为true") 10 ), 11 //如果条件false 12 Expression.Call( 13 null, 14 typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), 15 Expression.Constant("条件为false") 17 ); 18 //编译表达式树,输出结果 19 Expression.Lambda Action (codition).Compile()();
![复制代码](http://common.cnblogs.com/images/copycode.gif)
输出结果
例子描述:条件test包装为常量表达式,因为test为true,所以执行iftrue的表达式,并调用WriteLine方法打印出信息。
赋值表达式=
还以上面为变量i赋值的例子为例
1 ParameterExpression i = Expression.Parameter(typeof(int), "i"); 2 //ParameterExpression j = Expression.Variable(typeof(int), "j"); 3 ConstantExpression constExpr = Expression.Constant(5, typeof(int)); 4 // 创建一个表示赋值运算的 System.Linq.Expressions.BinaryExpression 5 //表示包含二元运算符的表达式。 6 BinaryExpression binaryExpression = Expression.Assign(i, constExpr);
+=
1 BinaryExpression b2 = Expression.AddAssign(i, constExpr);
-=
1 BinaryExpression b3 = Expression.SubtractAssign(i, constExpr);
*=
BinaryExpression b4 = Expression.MultiplyAssign(i, constExpr);
/=
1 BinaryExpression b5= Expression.DivideAssign(i, constExpr);
举一个例子
![复制代码](http://common.cnblogs.com/images/copycode.gif)
1 ParameterExpression i = Expression.Parameter(typeof(int), "i"); 2 BlockExpression block = Expression.Block( 3 new[] { i }, 4 //赋初值 i=5 5 Expression.Assign(i, Expression.Constant(5, typeof(int))), 6 //i+=5 10 7 Expression.AddAssign(i, Expression.Constant(5, typeof(int))), 8 //i-=5 5 9 Expression.SubtractAssign(i, Expression.Constant(5, typeof(int))), 10 //i*=5 25 11 Expression.MultiplyAssign(i, Expression.Constant(5, typeof(int))), 12 //i/=5 5 13 Expression.DivideAssign(i, Expression.Constant(5, typeof(int))) 14 ); 15 Console.WriteLine(Expression.Lambda Func int (block).Compile()());
![复制代码](http://common.cnblogs.com/images/copycode.gif)
结果
在上面也提到了部分二元运算符表达式,类似加减乘除这样的运算符,对于二元运算符,就不再举例。这些返回的表达式树,都可以使用BinaryExpression来接收,或者使用基类Expression接收,或者更省事,使用var关键字。
一元运算符表达式类似++,--运算符
i++等价于i=i+1,运算顺序就是i先加1,然后再赋值给i。在表达式书中使用Expression的PostIncrementAssign方法来进行自增或者自减操作。返回结果为UnaryExpression类型,同样可以使用基类Expression接收,或者var。
循环表达式在表达式树中使用Expression的Loop方法实现循环。
在前面的文章中,也说了不能使用Lambda方式创建带块级的表达式树,不然会有如下的错误
通过API的方式可以创建块级表达式树,其中Expression的Block方法功不可没。例如上面的加减乘除的例子中,可以包括多个Expression。
那么,下面就举一个包含自增的一元表达式,循环的表达式块,并输出结果。
输出1-100之间的所有偶数。
![复制代码](http://common.cnblogs.com/images/copycode.gif)
1 class Program 3 static void Main(string[] args) 5 //变量i 6 ParameterExpression i = Expression.Parameter(typeof(int), "i"); 7 //跳出循环 8 LabelTarget label = Expression.Label(); 9 BlockExpression block = Expression.Block( 10 new[] { i }, 11 //为i赋初值 12 Expression.Assign(i, Expression.Constant(1, typeof(int))), 13 Expression.Loop( 14 Expression.IfThenElse( 15 //如果i =100 16 Expression.LessThanOrEqual(i, Expression.Constant(100, typeof(int))), 17 //如果为true.进入循环体 18 Expression.Block( 19 Expression.IfThen( 20 //条件i%2==0; 21 Expression.Equal(Expression.Modulo(i, Expression.Constant(2, typeof(int))), 22 Expression.Constant(0, typeof(int))), 23 Expression.Call(typeof(Console).GetMethod("WriteLine", 24 new Type[] { typeof(int) }), new[] { i })), 25 //i++ 26 Expression.PostIncrementAssign(i) 27 ), 28 //如果i 100 29 Expression.Break(label)), 30 label 31 )); 32 Expression.Lambda Action (block).Compile()(); 33 Console.Read(); 35 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
结果
本篇文章介绍了几种常见的表达式类型,当然,还有很多并没有列出,比如switch case,try catch等。如果在项目中需要创建复杂的表达式树,Expression的静态方法Block是必不可少的。希望通过本篇的学习,对你了解Expression有所帮助。
参考文章
https://msdn.microsoft.com/zh-cn/library/dd323961(v=vs.110).aspx
https://msdn.microsoft.com/zh-cn/library/bb397951.aspx
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!
再次感谢您耐心的读完本篇文章。http://www.cnblogs.com/wolf-sun/p/4234747.html
表达式引擎--OGNL OGNL (Object Graph Navigation Language) 是一个开源的表达式引擎。通过使用OGNL,我们能够通过表达式存取Java对象树中的任意属性和调用Java对象树的方法等。也就是说,如果我们把表达式看成是一个带有语义的字符串,那么OGNL就是这个语义字符串与Java对象之间沟通的催化剂,通过OGNL,我们可以轻松解决在数据流转的过程中所碰到的各种问题。
普通表:存储客户数据,千万级别,结构如下 stat_date代表日期;user_id代表用户id;serial_number代表手机号;A_I72和A_I59是标签字段。
Kotlin的很多概念跟JAVA是有类似的,所以我应该不会像我的JAVA之旅一样那么的详细,但是不用担心,你会看的很明白的,我也是根据官方的文档来学习的 我们在IDEA中创建一个项目Kotlin02
相关文章
- 常见四大类型视频接线DP、HDMI、DVI、VGA的比较
- C++判断两个double类型双精度浮点数是否同号
- springMVC4(10)强大类型转换器实例解析
- RocketMQ 的消费者类型详解与最佳实践
- C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解
- 非托管类型转换为托管类型对照表
- k8s pod和service的关系及常用service类型:ClusterIP/NodePort/LoadBalancer
- ASP.NET Core的几种服务器类型[共6篇]
- Attit 现代编程语言重要特性目录第一章 类型系统 基本三大类型 2第一节 字符串 数字 bool 2第二节 推断局部变量 2第三节 动态类型 2第二章 可读性与开发效率 简单性 2
- Atitit json数据操作法 目录 1. 2. 常用json函数类型四大类型 crud&判断1 1.1. 2.1. 创建json21 1.2. 2.2. 选择与读取3读取数据读取key
- ML之FE:特征工程中常用的五大数据集划分方法(特殊类型数据分割,如时间序列数据分割法)讲解及其代码
- Algorithm:数学建模大赛(国赛和美赛)的简介/内容、数学建模做题流程、历年题目类型及思想、常用算法、常用工具之详细攻略
- ML之catboost:catboost模型中常用的Pool类型数据结构源代码解读、案例应用之详细攻略
- 【Android 安全】DEX 加密 ( Application 替换 | 获取 ContextImpl、ActivityThread、LoadedApk 类型对象 | 源码分析 )
- Java泛型:类型擦除
- C/C++之32与64位类型取值范围(六十七)
- 【SQL开发实战技巧】系列(四十五):Oracle12C常用新特性☞VARCHAR2/NVARCHAR2类型最大长度由4000字节扩展到32767字节
- BigDecimal初始化不要用double类型
- 运行期类型鉴定
- C#将枚举类型转化为字符串及枚举类型常用操作
- Mysql中的varchar类型转换成int类型
- JS Number对象常用函数(数字类型常用函数)