表达式目录树
什么是表达式目录树呢?用于表示Lambda表达式逻辑的一种数据结构,表达式树也可以称作表达式目录树,它 将代码表示成一个对象树,而不是可执行的代码。这个跟汇编原理一样,我们找到关键字,把这些语句翻译成机器码,我们这里的关键字就是表达式树里面的节点,然后分析语法词法,最后变成机器可识别的指令。
表达式目录树有什么作用呢?我们在使用ef框架的时候经常使用linq,使用linq to sql 的时候有多种方式,直接写from xx select,也可以使用lambda表达式,都是把这种语法翻译成可执行的sql,这里我们就会把lambda表达式转换成表达式树,对这个语句进行翻译,然后再在数据库中执行SQL语句,把返回的结果再返回给一个 IQueryable集合
怎么使用呢?lambda 表达式被分配给Expressions类型的变量,则编译器可以执行代码以创建表示该 lambda 表达式的表达式树。
下面我们来看例子
using System.Linq.Expressions;
static void Main(string[] args)
{
Expression<Func<int, int, int>> expression = (a, b) => a + b;
var parmeter1 = expression.Parameters[0];
var parmeter2 = expression.Parameters[1];
BinaryExpression body = (BinaryExpression)expression.Body;
ParameterExpression left = (ParameterExpression)body.Left;
ParameterExpression right = (ParameterExpression)body.Right;
var symbols = body.NodeType;
int result = expression.Compile()(2, 3);
Console.WriteLine("表达式:{0}", parmeter1);
Console.WriteLine("表达式体:{0}", body);
Console.WriteLine("表达式左边节点:{0}", left);
Console.WriteLine("表达式右边节点:{0}", right);
Console.WriteLine("表达式符号:{0}", symbols);
Console.WriteLine("表达式执行结果:{0}", result);
Console.Read();
}
执行结果如下:
表达式:a
表达式体:(a + b)
表达式左边节点:a
表达式右边节点:b
表达式符号:Add
表达式执行结果:5
创建表达式目录树
这里我们用表达式创建表达式:(a, b) => (a + b)
int a = 100;
int b = 200;
ParameterExpression left = Expression.Parameter(typeof(int), "a");
ParameterExpression right = Expression.Parameter(typeof(int), "a");
BinaryExpression binary = Expression.Add(left, right);
Expression<Func<int, int, int>> expression = Expression.Lambda<Func<int, int, int>>(binary, left, right);
Console.WriteLine($"{expression.ToString()}");//结果:(a, b) => (a + b)
Console.WriteLine(expression.Compile().Invoke(a, b));//调用
下面我们再来一个,x=>x.ID.ToString().Equals("3")
我们先来分析下这里的步骤,首先是x找到ID字段,然后执行ToString()方法,最后执行Equals("3")
我们来看代码
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
//定义x
ParameterExpression parameterExpression = Expression.Parameter(typeof(Student), "x");
//定义匹配常量
var constant = Expression.Constant("3");
var filedId = typeof(Student).GetProperty("ID");
//x.ID
var filedExp = Expression.Property(parameterExpression, filedId);
//调用ToString()
var toString = typeof(int).GetMethod("ToString", new Type[] { });
//x.ID.ToString()
var toStringExp = Expression.Call(filedExp, toString, new Expression[0]);
//调用Equals()
var equals = typeof(string).GetMethod("Equals", new Type[] { typeof(string) });
//x.ID.ToString().Equals("3")
var equalsExp = Expression.Call(toStringExp, equals, new Expression[] { constant });
//表达式目录树转lambda表达式 x=>x.ID.ToString().Equals("3")
Expression<Func<Student, bool>> expression = Expression.Lambda<Func<Student, bool>>(equalsExp, new ParameterExpression[]
{
parameterExpression
});
//执行 true
bool result = expression.Compile()(new Student()
{
ID =3,
Name ="张三",
Age =20
});