转载

[.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

[.net  面向对象程序设计进阶 ] (5) Lamda表达式 ( 表达式树快速入门

本节导读:

认识表达式树 ( Expression Tree) ,学习使用 Lambda 创建表达式树,解析表达式树。

学习表达式在程序设计中的优点:比如构造动态查询、动态构造表达式树完成未知对象属性访问,比反射的性能高出很多。我们可以说表达式树才是 L ambda的精髓,是我们必须要熟练掌握并灵活运用的。

1.关于表达式树(Expression Tree)

表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和  x < y  这样的二元运算等。

表达式树,对于刚接触的人来说,比较难以理解。那么什么是表达式树,通俗点来说,就是使用一种树形的数据结构来缓存表达式。

2.表达式树能帮我们做点什么?

上面我们说了表达式树是一种数据结构,那么为什么要把表达式定义成表达式树呢,转成一种数据结构,能帮我们做点什么?先明确了他能为我们带来什么,才有动力继续看下去。

说到他的作用,当然是非常有用的,我们在很多场景下都要使用他, 当表达式变为一个表达式树的数据结构时,表达式就变为一个对象,你可以对表达式树中的对象元素(表达式的代码)进行编辑和运算 。下面列举几种常用的:

  1. 通过修改表达式树能够动态修改可执行代码
  2. 在不同数据库中执行  LINQ  查询
  3. 创建动态查询。
  4. 完成类似反射访问未知对象属性,通过动态构造表达式树,生成委托。

3. 表达式树的创建

命名空间: System.Linq.Expressions 

创建表达式树示例:

Expression<Func<int, int, bool>>  expression  =  (num,num2)=> num < num2;

这个语句包含三个部分:

  1. 一个声明 Func<int, int, int> function
  2. 一个等号: =
  3. 一个 lambda 表达式 (num,num2)=> num < num2;

expression 就是一个类型为Expression<T>的表达式树,可以看出,他并非是一个可执行代码,而是一种表达式树的数据结构。

4.  表达式树结构的构成

Expression<Func<int, int, bool>>  expression  =  (num,num2)=> num < num2;

通过监视我们定义好的表达式树,可以看到其构成   [.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

下面我们对几个重要属性说明:

  • Body:  得到表达式的主体 例:(num < num2)     其中, B ody中又包含属性 L eft和 R ight  在上例中分别为num和num2
  • Parameters:  得到 lambda 表达式的参数。  例 {num,num2}
  • NodeType:  获取树的节点的 ExpressionType。共 45 种不同值,包含所有表达式节点各种可能的类型。 例如返回常量,例如返回参数,例如取两个值的小值 (<) ,例如取两个值的大值 (>) ,例如将值相加 (+) ,等等。 例:Lambda
  • Type:  获取表达式的一个静态类型  例:Func<int, int, bool>    
  • ReturnType:这个是表达式的返回类型    例:bool

还有一些其他属性Name、 CanReduce 等,这些不是很常用。  

5.解析表达式树

我们了解了表达式树结构的组成,解析表达式变得相当容易了,下面我们直接通过一个示例来完成对一个表达式树的解析:  

//表达式树(Expression) Expression<Func<int, int, bool>> expression = (x, y) => x!=0 && x==y+1;  BinaryExpression exr = expression.Body as BinaryExpression; IReadOnlyList<ParameterExpression> param = expression.Parameters as IReadOnlyList<ParameterExpression>; BinaryExpression left = exr.Left as BinaryExpression; BinaryExpression right = exr.Right as BinaryExpression; ExpressionType exrType = exr.NodeType;  ParameterExpression leftLeft = left.Left as ParameterExpression; ConstantExpression leftRight = left.Right as ConstantExpression; ExpressionType leftType = left.NodeType;  ParameterExpression rightLeft = right.Left as ParameterExpression; BinaryExpression rightRight = right.Right as BinaryExpression; ExpressionType rightType = right.NodeType;  ParameterExpression rightRightLeft = rightRight.Left as ParameterExpression; ExpressionType rightRightType = rightRight.NodeType; ConstantExpression rightRightRight = rightRight.Right as ConstantExpression;            Console.WriteLine(exr.ToString());

表达式树的解析,里面的元素无非就下面几种:  

A.BinaryExpression  包含二元运算符的表达式

B.ParameterExpression 命名的参数表达式  ,一般是一组参数集合 IReadOnlyList<ParameterExpression>

C.ConstantExpression 常量值的表达式

D.ExpressionType节点类型

对于上面示例的表达树结构,我用图例的方式展现如下:

[.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

对于上面的结构,我们可以按上面代码中的对象元素变量与之一一对应如下图:

[.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

要点:

本节我们介绍了表达式树在 .NET 面向对象程序设计中的作用、表达式树的创建与解析,相信小伙伴们对表达式树这种结构比较了解了。

表达式树(Expression Tree)就是一种使用对象的方式来描述表达式。这也正是 .NET 一切皆是对象的思想体现。

下一节我们会介绍动态创建一个表达式树结构、会举列说明几种表达式树在 .NET 程序设计中的应用。

正文到此结束
Loading...