目录

写在前面

系列文章

Expression

表达式树创建方式

一个例子

总结

写在前面

上篇文章介绍了扩展方法,这篇文章开始将陆续介绍在linq中使用最多的表达式树的相关概念,以概念及例子一一列出如何在代码中使用Expression。

系列文章

Linq之Lambda表达式初步认识

Linq之Lambda进阶

Linq之隐式类型、自动属性、初始化器、匿名类

Linq之扩展方法

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初见的更多相关文章

  1. Linq之Expression高级篇(常用表达式类型)

    目录 写在前面 系列文章 变量表达式 常量表达式 条件表达式 赋值表达式 二元运算符表达式 一元运算符表达式 循环表达式 块表达式 总结 写在前面 首先回顾一下上篇文章的内容,上篇文章介绍了表达式树的 ...

  2. Linq之Expression进阶

    目录 写在前面 系列文章 表达式树解析 表达式树特性 编译表达树 总结 写在前面 让我们首先简单回顾一下上篇文章介绍的内容,上篇文章介绍了表达式树的基本概念(表达式树又称为“表达式目录树”,以数据形式 ...

  3. 动态拼接linq 使用Expression构造动态linq语句

    最近在做动态构造linq语句,从网上找了很多,大多数,都是基于一张表中的某一个字段,这样的结果,从网上可以搜到很多.但如果有外键表,需要动态构造外键表中的字段,那么问题来了,学挖掘机哪家强?哦,不是, ...

  4. LINQ的Expression与delegate表达式

    Linq的delegate表达式,Insus.NET觉得它封装得好,让开发时简化了很多代码,而且容易阅读与检索. 比如,我们需要计算优惠给客户金额,打85%折,可以这样写: using System; ...

  5. linq入门系列导航

    写在前面 为什么突然想起来学学linq呢?还是源于在跟一个同事聊天的时候,说到他们正在弄得一个项目,在里面用到了linq to sql.突然想到距上次使用linq to sql是三年前的事情了.下班回 ...

  6. Linq之Linq to Sql

    目录 写在前面 系列文章 Linq to sql 总结 写在前面 上篇文章介绍了linq to xml的相关内容,linq to xml提供一种更便捷的创建xml树,及查询的途径.这篇文章将继续介绍l ...

  7. Linq之Linq to XML

    目录 写在前面 系列文章 linq to xml 总结 写在前面 在很多情况下,都可以见到使用xml的影子.例如,在 Web 上,在配置文件.Microsoft Office Word 文件(将wor ...

  8. Linq之Linq to Objects

    目录 写在前面 系列文章 linq to objects 总结 写在前面 上篇文章介绍了linq的延迟加载特性的相关内容,从这篇文章开始将陆续介绍linq to Objects,linq to xml ...

  9. Linq之延迟加载特性

    目录 写在前面 系列文章 延迟加载 总结 写在前面 上篇文章介绍了linq中常见的几个关键字,并列举了几个例子,算是对linq如何使用有了初步了解.上篇文章中也提到了,能够使用linq的场合有一个要求 ...

随机推荐

  1. 02_嵌套矩形(DAG最长路问题)

    来源:刘汝佳<算法竞赛入门经典--训练指南> P60 问题2: 问题描述:有n个矩形,每个矩形可以用两个整数a,b描述,表示它们的长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中的条件 ...

  2. Heartbeat+LVS构建高可用负载均衡集群

    1.heartbeat简介: Heartbeat 项目是 Linux-HA 工程的一个组成部分,它实现了一个高可用集群系统.心跳服务和集群通信是高可用集群的两个关键组件,在 Heartbeat 项目里 ...

  3. POJ 2406 Power Strings (KMP)

    Power Strings Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 29663Accepted: 12387 Descrip ...

  4. DFS cdoevs 3100 蜗牛

    cdoevs 3100 蜗牛  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 黄金 Gold 题目描述 Description 萨丽·斯内尔(Sally Snail,蜗牛)喜欢在 ...

  5. hdu-5927 Auxiliary Set(树形dp)

    题目链接: Auxiliary Set Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  6. 实习小记-python中不可哈希对象设置为可哈希对象

    在这篇之前,我又专门翻译过官方python3.3的可哈希对象文档,大家可以先参考一下: 实习小记-python中可哈希对象是个啥?what is hashable object in python? ...

  7. mac os利用xampp实现apache下的cgi

    折腾了两天终于把问题解决了,mac os是10.10.3..够新了吧 系统原生的apache配置cgi老是配不好,突然发现xampp也有macos版的,准备下下来试试. 安装完成后,打开apache服 ...

  8. UVA 11992 Fast Matrix Operations (二维线段树)

    解法:因为至多20行,所以至多建20棵线段树,每行建一个.具体实现如下,有些复杂,慢慢看吧. #include <iostream> #include <cstdio> #in ...

  9. Android数据存储(二)----PreferenceFragment详解

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  10. Apache Shiro权限框架在SpringMVC+Hibernate中的应用

    在做网站开发中,用户权限必须要考虑的,权限这个东西很重要,它规定了用户在使用中能进行哪 些操作,和不能进行哪些操作:我们完全可以使用过滤器来进行权限的操作,但是有了权限框架之后,使用起来会非常的方便, ...