表达式树摘录(1)
本文主要讲述
ConstantExpression介绍 表示具有常量值的表达式。
ParameterExpression介绍 表示命名的参数表达式。
UnaryExpression介绍 表示包含一元运算符的表达式。
BinaryExpression介绍 表示包含二元运算符的表达式。
NewExpression介绍 表示调用构造函数,实例化对象的表达式。
NewArrayExpression介绍 表示创建新数组并可能初始化该新数组的元素的表达式。
TypeBinaryExpression介绍 表示表达式和类型之间的操作。
说明
上面列出的各个子Expression均派生自Expression类,并继承了NodeType,Type属性,这些将不再在下文说明,并且各个子Expression的构造函数都是Internal的,这意味着我们不能通过new 某个Expression来获得它的实例,而必须通过Expreesion类提供的工厂方法来创建。
ConstantExpression介绍
该类封装了一个表示包含常量值的表达式, 使用 Constant 工厂方法可创建 ConstantExpression ,它的 NodeType 为 Constant。
主要属性
Value 获取常量表达式的值,返回Object类型
工厂方法
Constant(Object) 创建一个设置为指定值的 ConstantExpression。
Constant(Object,Type) 创建一个设置为指定值,并指定值的类型的 ConstantExpression。
示例
运行结果:
ParameterExpression介绍
该类封装了表示命名参数的表达式,可以使用 Parameter工厂方法创建ParameterExpression,它的NodeType属性为 Parameter。
主要属性
Name 获取参数名,返回String类型
工厂方法
Parameter(Type,String) 创建一个具有指定名称和类型的参数的 ParameterExpression
示例
运行结果:
该类主要封装了一个表示一元运算符的表达式数据结构。
主要属性
IsLifted 获取一个值, 该值指示表达式树节点是否表示对运算符的提升调用。
IsLiftedToNull 获取一个值,该值指示表达式树节点是否表示对运算符(其返回类型提升为可以为null的类型)的提升调用。
Method 获取一元运算符的实现方法,返回 MethodInfo 类型 。
Operand 获取一元运算符的操作数,返回 Expression 类型。
工厂方法和对应的节点类型
工厂方法 节点类型
ArrayLength ArrayLength
Convert Convert
ConvertChecked ConvertChecked
Negate Negate
NegateChecked NegateChecked
Not Not
Quote Quote
TypeAs TypeAs
UnaryPlus UnaryPlus
还可以通过MakeUnary方法创建以上任何一种节点类型的UnaryExpression。
示例
结果
该类封装了表示二元运算符的表达式,并且提供了一些属性用于访问二元运算符的左操作数和右操作数,以及之间的转换函数,由于二元运算符应用的比较广泛,所以下面详细的介绍一下BinaryExpression。
主要属性
Conversion 获取合并运算使用的类型转换函数。
IsLifted 获取一个值,该值指示表达式树节点是否表示对运算符的提升调用。
IsLiftedToNull 获取一个值,该值指示表达式树节点是否表示对运算符(其返回类型提升为可以为 null 的类型)的提升调用。
Left 获取二元运算符的左操作数
Method 获取二元运算的实现方法
Right 获取二元运算的右操作数
什么是二元运算符?
用来连接两个操作数的运算符就叫二元运算符,它包含(+、-、*、/、%、&、|、^、<<、>>、==、!=、>、<、>= 或 <=),由这些符号组成的表达式又叫“
二元运算符表达式“。如:相加运算符、相减运算符等等。
1 +2;
a - b;
(k * 5) % 2
实际上,Expression类中定义了一套与之对应的工厂方法来创建某种具体的二元运算符表达式,如:
+ Add 、 AddChecked
- Subtract 、SubtractChecked
* Multiply, MultiplyChecked
/ Divide
% Modulo
= Equal
!= NotEqual
> GreaterThan
>= GreaterThanOrEqual
< LessThan
<= LessThanOrEqual
& And
&& AndAlso
| Or
|| OrElse
?? Coalesce
^ ExclusiveOr
^ Power
<< LeftShift
>> RightShift
从文档上看BinaryExpression内并不包含任何方法,只是包含了少量几个只读的属性,所以直接通过BinaryExpression创建实例似乎是不可能的, 于是尝试从父类Expression类来创建,果然找到了如下一些方法:
观察上面的方法发现每个参数都带有一个left 和 right的参数,它表示BinaryExpression表达式两边的操作数,并且每个参数的类型都是抽象Expression类型,此外可以使用MakeBinary 方法创建以上任意一种节点类型的BinaryExpression,主要通过指定ExpressionType枚举来创建。
下面通过代码来实际应用一下:
NewExpression介绍
该类封装了表示创建一个对象的实例,并调用构造函数的表达式。 使用工厂方法New 来创建NewExpression, 节点类型为: New
主要属性
Arguments 获取构造函数的参数 , 返回类型 ReadOnlyCollection<Expression>
Constructor 获取被调用的构造函数 , 返回类型 ConstructorInfo
Members 获取已使用构造函数参数进行初始化的成员, 返回类型 ReadOnlyCollection<MemberInfo>
工厂方法
New( ConstuctorInfo) 创建一个表示调用不带参数的指定构造函数的NewExpression
New(Type) 创建一个表示调用指定类型的无参构造函数的NewExpression
New(ConstructorInfo, IEnumerable<Expression>) 创建一个表示调用带指定参数的指定构造函数的NewExpression
New(ConstructorInfo, Expression[]) 创建一个表示调用带指定参数的指定构造函数的NewExpression
New(ConstructorInfo, IEnumerable<Expression>, IEnumerable<MemberInfo>) 同上, 其中指定了访问构造函数初始化的字段的成员
New(ConstructorInfo, IEnumerable<Expression>, MemberInfo[]) 同上, 将访问构造函数初始化字段的成员指定为数组
示例
下面演示一些New工厂方法的应用.
结果
NewArrayExpression介绍
该类主要表示创建数组并可能初始化该数组的元素,主要通过工厂方法 NewArrayBounds、 或 NewArrayInit 创建NewArrayExpression。
主要属性
Expressions 如果NodeType值为 NewArrayBounds,则获取数组的界限; 如果为 NewArrayInit, 则获取用来初始化数组的元素的值。
NewArrayInit(Type, IEnumerable<Expression>) 创建一个表示一维数组并使用元素列表初始化该数组的 NewArrayExpression
NewArrayInit(Type, Expression[] ) 创建一个表示一维数组并使用元素列表初始化该数组的 NewArrayExpression
NewArrayBounds(Type, IEnumerable<Expression> ) 创建一个表示具有指定维的数组的 NewArrayExpression
NewArrayBounds(Type, Expression [] ) 创建一个表示具有指定维的数组的 NewArrayExpression
示例
下面演示如何创建一个一维或多维数组的表达式
结果
TypeBinaryExpression介绍
该类表示表达式和类型之间的操作,例如 类型测试就是表达式和类型之间的操作。 使用工厂方法 TypeIs 方法创建TypeBinaryExpression,节点类型 TypeIs.
主要属性
Expression 获取类型测试操作的表达式操作数,返回Expression类型
TypeOperand 获取类型测试操作的类型操作数,返回Type类型
工厂方法
TypeIs(Expression, Type) 表示表达式和类型之间的操作
示例
结果