表达式树是一种数据结构,表达式树配合Linq可以完成非常丰富的操作,还可以进行动态操作,例如使用Entity Framework进行数据库操作时,我们可以通过表达式树进行动态查询语句的生成。表达式树支持动态生成、修改(重新创建一棵树)。
我们看一下简单的代码:
class ExpressionDemo
{
public static void ExpMain()
{
//BinaryExpression--表示具有二进制运算符的表达式
//ParameterExpression--表示一个命名的参数表达式
//ConstantExpression--表示具有常数值的表达式
//Expression--表达式树基类,以上类型均派生自Expression
{
Expression<Func<int, int, int>> expression = (x, y) => x * y;//生成乘法表达式
var func = expression.Compile();//编译表达式
Console.WriteLine(expression.Body + "=" + func(1, 2));//输出表达式并输出执行结果
Expression<Func<int, int, int>> expression1 = (x, y) => x + y;//生成加法表达式
var func1 = expression1.Compile();//编译表达式
Console.WriteLine(expression1.Body + "=" + func1(1, 2));//输出表达式并输出执行结果
}
{
ParameterExpression parameterX = Expression.Parameter(typeof(int), "x");//定义参数X
ParameterExpression parameterY = Expression.Parameter(typeof(int), "y");//定义参数Y
BinaryExpression binaryAdd = Expression.Add(parameterX, parameterY);//定义加法表达式(x+y)
BinaryExpression binaryMultiply = Expression.Multiply(parameterX, parameterY);//定义乘法表达式(x*y)
ConstantExpression constant = Expression.Constant(10, typeof(int));//定义常量10
ConstantExpression constant2 = Expression.Constant(5, typeof(int));//定义常量5
BinaryExpression binaryAdd2 = Expression.Add(binaryAdd, binaryMultiply);//(拼接)加法表达式 + 乘法表达式((x+y)+(x*y))
BinaryExpression binaryAdd3 = Expression.Add(binaryAdd2, constant);//上一步表达式+常数表达式((x+y)+(x*y)+10) 加法运算
BinaryExpression binarySubtract = Expression.Subtract(binaryAdd3, constant2);//上一步表达式-常数表达式(((x+y)+(x*y)+10)-5) 减法运算
var expression = Expression.Lambda<Func<int, int, int>>(binarySubtract, parameterX, parameterY);//创建表达式树
var func = expression.Compile();//编译表达式树并生成委托
Console.WriteLine(expression.Body + "=" + func(2, 3));//输出表达式并输出执行结果
}
{
ParameterExpression parameterX = Expression.Parameter(typeof(int), "x");//定义参数X
ParameterExpression parameterY = Expression.Parameter(typeof(int), "y");//定义参数Y
ConstantExpression constant = Expression.Constant(0, typeof(int));//定义常量0
BinaryExpression binary = Expression.Equal(parameterX, parameterY);//(x==y)
BinaryExpression binary1 = Expression.GreaterThan(parameterX, constant);//(x>0)
BinaryExpression binary2 = Expression.GreaterThan(parameterY, constant);//(y>0)
BinaryExpression binary3 = Expression.AndAlso(binary1, binary2);//((x>0)&&(y>0))
BinaryExpression binary4 = Expression.And(binary, binary3);//(x==y)&((x>0)&&(y>0))
var expression = Expression.Lambda<Func<int, int, bool>>(binary4, parameterX, parameterY);
var func = expression.Compile();
Console.WriteLine(expression.Body + "=" + func(1, 1));//判断入参是否相等并且大于0
}
}
}
运行结果:
下面列出表达式树相关类型:
类型 | 说明 |
BinaryExpression | 表示具有二进制运算符的表达式。 |
BlockExpression | 表示包含一个表达式序列的块,表达式中可定义变量。 |
CatchBlock | 表示 try 块中的 catch 语句。 |
ConditionalExpression | 表示具有条件运算符的表达式。 |
ConstantExpression | 表示具有常数值的表达式。 |
DebugInfoExpression | 发出或清除调试信息的序列点。 这使调试器能够在调试时突出显示正确的源代码。 |
DefaultExpression | 表示一个类型或空表达式的默认值。 |
DynamicExpression | 表示一个动态操作。 |
DynamicExpressionVisitor | 表示动态表达式树的访问者或重写者。 |
ElementInit | 表示 IEnumerable 集合的单个元素的初始值设定项。 |
Expression<TDelegate> | 将强类型化的 Lambda 表达式表示为表达式树形式的数据结构。 此类不能被继承。 |
ExpressionVisitor | 表示表达式树的访问者或重写者。 |
GotoExpression | 表示无条件跳转。 这包括返回语句,break 和 continue 语句以及其他跳转。 |
IndexExpression | 表示对一个属性或数组进行索引。 |
InvocationExpression | 表示一个将委托或 Lambda 表达式应用到一个自变量表达式列表的表达式。 |
LabelExpression | 表示一个标签,可以将该标签放置在任何 Expression 上下文中。 如果已跳转到该标签,则它将获取由对应的 GotoExpression 提供的值。 否则,它接收 DefaultValue 中的值。 如果 Type 等于 System.Void,则不应提供值。 |
LabelTarget | 用于表示 GotoExpression 的目标。 |
LambdaExpression | 介绍 lambda 表达式。 它捕获一个类似于 .NET 方法主体的代码块。 |
ListInitExpression | 表示具有集合初始值设定项的构造函数调用。 |
LoopExpression | 表示无限循环。 可通过“中断”退出该循环。 |
MemberAssignment | 表示对象的字段或属性的赋值操作。 |
MemberBinding | 提供表示绑定的类派生自的基类,这些绑定用于对新创建对象的成员进行初始化。 |
MemberExpression | 表示访问字段或属性。 |
MemberInitExpression | 表示调用构造函数并初始化新对象的一个或多个成员。 |
MemberListBinding | 表示初始化新创建对象的一个集合成员的元素。 |
MemberMemberBinding | 表示初始化新创建对象的一个成员的成员。 |
MethodCallExpression | 表示对静态方法或实例方法的调用。 |
NewArrayExpression | 表示创建一个新数组,并可能初始化该新数组的元素。 |
NewExpression | 表示一个构造函数调用。 |
ParameterExpression | 表示一个命名的参数表达式。 |
RuntimeVariablesExpression | 一个为变量提供运行时读/写权限的表达式。 |
SwitchCase | 表示 SwitchExpression 的一个事例。 |
SwitchExpression | 表示一个控制表达式,该表达式通过将控制传递到 SwitchCase 来处理多重选择。 |
SymbolDocumentInfo | 存储用于发出源文件调试符号信息所必要的信息,尤其是文件名和唯一的语言标识符。 |
TryExpression | 表示一个 try/catch/finally/fault 块。 |
TypeBinaryExpression | 表示表达式和类型之间的操作。 |
UnaryExpression | 表示具有一元运算符的表达式。 |
表格中这些类型都继承自 Expression 类,可以使用该类型并配合相关派生类型生成任何你需要的表达式类型。