Expression< Func<string , bool >> filter = x => x == "zhangsan" ;
var compile = filter.Compile();
bool iszhangsan = compile("zhangsan" );
Console.WriteLine(iszhangsan);
Console.ReadKey();
也可以对树的结构进行解析,
Expression<Func <string, bool>> filter = x => x == "zhangsan" ;
//我们可以对这个表达式树进行解析
//从名称也可以看出来二叉树
BinaryExpression body = (BinaryExpression)filter.Body;
ParameterExpression left = (ParameterExpression)body.Left;
ConstantExpression right = (ConstantExpression)body.Right;
string type = body.NodeType.ToString();
Console.WriteLine("树的左边是{0},节点符号{1},树的右边{2}" ,left,type,right);
表达式树最大的用处并不是多此一举的编译成匿名方法执行,而是 在于它可以存储 我个人认为叫做“行为信息”
将可执行代码(如C#代码) 转化成 行为数据信息(expression) 然后在转化为针对其他程序的可执行代码(如sql)
说的更莽撞点,就是一个符合一定规范的lambda语句,如果是表达式树的话,就会对其进行词法分析语法分析,成为一个表示行为信息的数据结构而已。
(注意并不是所有的lambda表达式都可以转化成表达式树)
而上述思想的一个很辉煌的实现就是 Linq,尤其是linq to sql
先看一下这样一个 linq 语句
var query = from c in db.Customers
where c.City == "Nantes"
select new { c.City, c.CompanyName };
linq to sql 返回的是 IQueryable类型,我们看一下IQueryable的定义
可以看到存在一个表达式树,这个表达式树就存储了上面的linq 语句想要表达的行为信息,而provider则可以显示出接下来就翻译这个行为信息成为新的可执行代码的程序,如linq to sqlserverprovider (自带) linq to oracle
等。
而之所以要进行这样由C#代码翻译成表达式树数据信息在翻译成可执行代码的原意在于。你最终是要生成sql语句串通过网络发送到远程数据库在查询出结果才可以嘛。
当然如何从上面的代码得出表达式树,又怎么分析得出合适的sql语句就不在讨论范围之内了,这里面有比较复杂的算法。
对于linq to objects 返回的则是IEnumerable 里面就不需要什么表达式树来存储信息了,因为本身就是针对处于同一块内存中的数据进行查询,直接逻辑查找就可以了。
就是因为 借助了强大的表达式树,linq蓬勃发展,比如linq to amazon 项目就是要将表达式树分析然后转化成webservice再执行各种操作。
最后总结 表达式树是为了存储行为信息,以用来跟各种程序交互,实现 不同平台不同语言之间可执行代码的转变。