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的场合有一个要求 ...
随机推荐
- 02_嵌套矩形(DAG最长路问题)
来源:刘汝佳<算法竞赛入门经典--训练指南> P60 问题2: 问题描述:有n个矩形,每个矩形可以用两个整数a,b描述,表示它们的长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中的条件 ...
- Heartbeat+LVS构建高可用负载均衡集群
1.heartbeat简介: Heartbeat 项目是 Linux-HA 工程的一个组成部分,它实现了一个高可用集群系统.心跳服务和集群通信是高可用集群的两个关键组件,在 Heartbeat 项目里 ...
- POJ 2406 Power Strings (KMP)
Power Strings Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 29663Accepted: 12387 Descrip ...
- DFS cdoevs 3100 蜗牛
cdoevs 3100 蜗牛 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description 萨丽·斯内尔(Sally Snail,蜗牛)喜欢在 ...
- hdu-5927 Auxiliary Set(树形dp)
题目链接: Auxiliary Set Time Limit: 9000/4500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- 实习小记-python中不可哈希对象设置为可哈希对象
在这篇之前,我又专门翻译过官方python3.3的可哈希对象文档,大家可以先参考一下: 实习小记-python中可哈希对象是个啥?what is hashable object in python? ...
- mac os利用xampp实现apache下的cgi
折腾了两天终于把问题解决了,mac os是10.10.3..够新了吧 系统原生的apache配置cgi老是配不好,突然发现xampp也有macos版的,准备下下来试试. 安装完成后,打开apache服 ...
- UVA 11992 Fast Matrix Operations (二维线段树)
解法:因为至多20行,所以至多建20棵线段树,每行建一个.具体实现如下,有些复杂,慢慢看吧. #include <iostream> #include <cstdio> #in ...
- Android数据存储(二)----PreferenceFragment详解
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- Apache Shiro权限框架在SpringMVC+Hibernate中的应用
在做网站开发中,用户权限必须要考虑的,权限这个东西很重要,它规定了用户在使用中能进行哪 些操作,和不能进行哪些操作:我们完全可以使用过滤器来进行权限的操作,但是有了权限框架之后,使用起来会非常的方便, ...