Linq之Expression初见
目录
写在前面
上篇文章介绍了扩展方法,这篇文章开始将陆续介绍在linq中使用最多的表达式树的相关概念,以概念及例子一一列出如何在代码中使用Expression。
系列文章
Expression
还是老样子,首先看MSDN中对表达式树的描述
表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和 x < y 这样的二元运算等。
你可以对表达式树中的代码进行编辑和运算。 这样能够动态修改可执行代码、在不同数据库中执行 LINQ 查询以及创建动态查询。
表达式树又称为“表达式目录树”,以数据形式表示语言级代码,它是一种抽象语法树或者说是一种数据结构。
通过上面的描述,你会发现表达式树的作用:动态修改可执行代码、在不同数据库中执行Linq查询及创建动态查询。那它是如何做到的呢?那下面就开始咱们的表达式树之旅吧。
表达式树创建方式
表达式树创建方式分为两种:以lambda表达式的方式创建,通过API静态方法创建。
若 lambda 表达式被分配给 Expression<TDelegate> 类型的变量,则编译器可以发射代码以创建表示该 lambda 表达式的表达式树。
看一个例子:
static void Main(string[] args)
{
System.Linq.Expressions.Expression<Func<int, bool>> lambda = num => num >= ;
}
上面的代码意思就以表达式目录树的形式将强类型的lambda表达式num=>num>=5标识为数据结构。
通过 API 创建表达式树需要使用 Expression 类。
该类包含创建特定类型表达式树节点的静态工厂方法,比如表示参数变量的 ParameterExpression,或者是表示方法调用的 MethodCallExpression。 System.Linq.Expressions 名称空间还解释了 ParameterExpression、MethodCallExpression和另一种具体表达式类型。 这些类型来源于抽象类型 Expression。
那么我使用API的方式创建上面例子中的表达式树:
说的很高大上,其实就是类Expression的一系列静态方法。
首先引入命名空间
using System.Linq.Expressions;
static void Main(string[] args)
{
//创建lambda表达式 num=>num>=5
//第一步创建输入参数,参数名为num,类型为int类型
ParameterExpression numParameter = Expression.Parameter(typeof(int), "num");
//第二步创建常量表达式5,类型int
ConstantExpression constant = Expression.Constant(, typeof(int));
//第三步创建比较运算符>=,大于等于,并将输入参数表达式和常量表达式输入
//表示包含二元运算符的表达式。BinaryExpression继承自Expression
BinaryExpression greaterThanOrEqual = Expression.GreaterThanOrEqual(numParameter, constant);
//第四步构建lambda表达式树
//Expression.Lambda<Func<int, bool>>:通过先构造一个委托类型来创建一个 LambdaExpression
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(greaterThanOrEqual, numParameter);
}
通过上面的代码你会发现这种方式在创建的时候,lambda表达式的左右及二元运算符都要分别的创建,然后在通过Expression.Lambda方法构建lambda表达式。
一个例子
在 .NET Framework 4 中,API 表达式树还支持赋值表达式和控制流表达式,比如循环、条件块和 try-catch 块等。
看一个例子,通过API表达式树创建一个利用循环求1到n的和的表达式树。
如果能这样写该有多好啊
Expression<Func<int, int>> lambda = n =>
{
int result = ;
for (int j = n; j >= ; j--)
{
result += j;
}
return result;
};
可惜
通过API创建表达式树,可以创建更为复杂的表达式树,这里先尝尝鲜
class Program
{
static void Main(string[] args)
{
//变量表达式
ParameterExpression i = Expression.Variable(typeof(int), "i");
//变量表达式
ParameterExpression sum = Expression.Variable(typeof(int), "sum");
//跳出循环标志
LabelTarget label = Expression.Label(typeof(int));
//块表达式
BlockExpression block =
Expression.Block(
//添加局部变量
new[] { sum },
//为sum赋初值 sum=1
//Assign表示赋值运算符
Expression.Assign(sum, Expression.Constant(, typeof(int))),
//loop循环
Expression.Loop(
//如果为true 然后求和,否则跳出循环
Expression.IfThenElse(
//如果i>=0
Expression.GreaterThanOrEqual(i, Expression.Constant(, typeof(int))),
//sum=sum+i;i++;
Expression.AddAssign(sum, Expression.PostDecrementAssign(i)),
//跳出循环
Expression.Break(label, sum)
), label
) // Loop ends
);
int resutl = Expression.Lambda<Func<int, int>>(block, i).Compile()();
Console.WriteLine(resutl);
Console.Read();
}
}
输出结果
总结
本篇文章主要介绍了表达式树的概念及两种创建方式。在文章的结尾给出了一个例子,也是先尝尝鲜,对于代码中的一些静态方法可先参考注释。下篇文章将介绍一些Expression的常用的静态方法。
参考文章
http://msdn.microsoft.com/zh-cn/library/bb397951.aspx
Linq之Expression初见的更多相关文章
- Linq之Expression高级篇(常用表达式类型)
目录 写在前面 系列文章 变量表达式 常量表达式 条件表达式 赋值表达式 二元运算符表达式 一元运算符表达式 循环表达式 块表达式 总结 写在前面 首先回顾一下上篇文章的内容,上篇文章介绍了表达式树的 ...
- Linq之Expression进阶
目录 写在前面 系列文章 表达式树解析 表达式树特性 编译表达树 总结 写在前面 让我们首先简单回顾一下上篇文章介绍的内容,上篇文章介绍了表达式树的基本概念(表达式树又称为“表达式目录树”,以数据形式 ...
- 动态拼接linq 使用Expression构造动态linq语句
最近在做动态构造linq语句,从网上找了很多,大多数,都是基于一张表中的某一个字段,这样的结果,从网上可以搜到很多.但如果有外键表,需要动态构造外键表中的字段,那么问题来了,学挖掘机哪家强?哦,不是, ...
- LINQ的Expression与delegate表达式
Linq的delegate表达式,Insus.NET觉得它封装得好,让开发时简化了很多代码,而且容易阅读与检索. 比如,我们需要计算优惠给客户金额,打85%折,可以这样写: using System; ...
- linq入门系列导航
写在前面 为什么突然想起来学学linq呢?还是源于在跟一个同事聊天的时候,说到他们正在弄得一个项目,在里面用到了linq to sql.突然想到距上次使用linq to sql是三年前的事情了.下班回 ...
- Linq之Linq to Sql
目录 写在前面 系列文章 Linq to sql 总结 写在前面 上篇文章介绍了linq to xml的相关内容,linq to xml提供一种更便捷的创建xml树,及查询的途径.这篇文章将继续介绍l ...
- Linq之Linq to XML
目录 写在前面 系列文章 linq to xml 总结 写在前面 在很多情况下,都可以见到使用xml的影子.例如,在 Web 上,在配置文件.Microsoft Office Word 文件(将wor ...
- Linq之Linq to Objects
目录 写在前面 系列文章 linq to objects 总结 写在前面 上篇文章介绍了linq的延迟加载特性的相关内容,从这篇文章开始将陆续介绍linq to Objects,linq to xml ...
- Linq之延迟加载特性
目录 写在前面 系列文章 延迟加载 总结 写在前面 上篇文章介绍了linq中常见的几个关键字,并列举了几个例子,算是对linq如何使用有了初步了解.上篇文章中也提到了,能够使用linq的场合有一个要求 ...
随机推荐
- CVE
一.简介 CVE 的英文全称是"Common Vulnerabilities & Exposures"公共漏洞和暴露.CVE就好像是一个字典表,为广泛认同的信息安全漏洞或者 ...
- 利用模板在RM里部署VM
Refer to: https://www.azure.cn/documentation/articles/virtual-machines-windows-ps-template/ 过程中遇到的几个 ...
- Error during installing HAXM, VT-X not working 在安装HAXM错误,开始不工作
最佳答案 (Best Answer) Some antivirus options prevent Haxm installation. ie: Avast : settings (parametre ...
- 平摊分析 Amortized Analysis ------geeksforgeeks翻译
当偶尔一切操作很花的时间很慢,而大多数操作的时间都很快的时候,平摊分析的方法就很很好用了.在平摊分析中,我们分析一串操作并且可以得到最坏情况下的平均时间复杂度.例如hash table, disjoi ...
- UESTC 424 AreYouBusy --混合背包
混合三种背包问题. 定义:dp[i][k]表示体积为k的时候,在前i堆里拿到的最大价值. 第一类,至少选一项,dp初值全赋为负无穷,这样才能保证不会出现都不选的情况.dp[i][k] = max(dp ...
- Watir、Selenium2、QTP区别
1.支持的语言 Watir:ruby Selenium2:支持多种语言,如:python,ruby,java,c#,php,perl,javascript QTP:vbscript 2.支持的浏览器 ...
- maven总结1
环境:win7 maven版本:apache-maven-3.1.1-bin.zip maven安装 1.确定已经正确安装jdk,若未安装需要先安装jdk 2.http://maven.apac ...
- java 21-11 数据输入、输出流和内存操作流
IO数据流: 可以读写基本数据类型的数据 数据输入流:DataInputStream DataInputStream(InputStream in) 数据输出流:DataOutputStream ...
- app:transformClassesWithJarMergingForDebug uplicate entry: android/support/v4/app/BackStackState$1.class
.Execution failed for task ':app:transformClassesWithJarMergingForDebug'.> com.android.build.api. ...
- 分享一例脚本发版和tomcat重启脚本
线上有个网站业务部署在tomcat上,由于频繁上线修改,需要经常启动tomcat.tomcat服务自带的bin下没有重启脚本,下面分享一例脚本发版和tomcat重启脚本: 1)现将业务代码从svn里下 ...