目录

写在前面

系列文章

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. apache加载php配置

    #载入php模块和ini路径,以及凡是.php开头的以它来处理 LoadModule php5_module E:/server/php/php5apache2_2.dll PHPIniDir &qu ...

  2. 【读书笔记《Android游戏编程之从零开始》】11.游戏开发基础(SurfaceView 游戏框架、View 和 SurfaceView 的区别)

    1. SurfaceView 游戏框架实例 实例效果:就是屏幕上的文本跟着点击的地方移动,效果图如下: 步骤: 新建项目“GameSurfaceView”,首先自定义一个类"MySurfac ...

  3. codeforces 710E E. Generate a String(dp)

    题目链接: E. Generate a String time limit per test 2 seconds memory limit per test 512 megabytes input s ...

  4. DragRigidbody2D

    组件源码 using UnityEngine; using System.Collections; //This script allows to drag rigidbody2D elements ...

  5. 查看mysqll账号信息

    也可以删除,和操作其他普通表一样

  6. center

    center标签对其包围的文本进行水平居中处理

  7. poj 1411 Calling Extraterrestrial Intelligence Again(超时)

    Calling Extraterrestrial Intelligence Again Time Limit: 1000MS   Memory Limit: 65536K Total Submissi ...

  8. 15SpringMvc_在业务控制方法中写入模型变量收集参数,且使用@InitBind来解决字符串转日期类型

    之前第12篇文章中提到过在业务控制方法中写入普通变量收集参数的方式,也提到了这种凡方式的弊端(参数很多怎么办),所以这篇文章讲的是在业务控制方法中写入模型变量来收集参数.本文的案例实现的功能是,在注册 ...

  9. RDLC系列之一 简单示例

    参照文章:http://www.cnblogs.com/waxdoll/archive/2006/07/24/458409.html#!comments 一.效果图

  10. 安装和使用Karma-Jasmine进行自动化测试

    注意:本文中出现的资料链接.karma的插件安装等,均可能需要翻$墙后才能正确执行. Jasmine是一个Javascript的测试工具,在Karma上运行Jasmine可完成Javascript的自 ...