天天看点

Linq之Expression进阶

<a href="http://www.cnblogs.com/wolf-sun/p/4230226.html#t1" target="_blank">写在前面</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4230226.html#t2" target="_blank">系列文章</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4230226.html#t3" target="_blank">表达式树解析</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4230226.html#t4" target="_blank">表达式树特性</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4230226.html#t5" target="_blank">编译表达树</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4230226.html#t6" target="_blank">总结</a>

让我们首先简单回顾一下上篇文章介绍的内容,上篇文章介绍了表达式树的基本概念(表达式树又称为“表达式目录树”,以数据形式表示语言级代码,它是一种抽象语法树或者说是一种数据结构),以及两种创建表达式树目录树的方式:以lambda表达式的方式创建,通过api静态方法创建。由于不能将有语句体的lambda表达式转换为表达式树,而有时我们又有这样的需求,那么这种情况你可以选择api的静态方法方式创建,在 .net framework 4 中,api 表达式树还支持赋值表达式和控制流表达式,比如循环、条件块和 try-catch 块等。

<a href="http://www.cnblogs.com/wolf-sun/p/4199383.html">linq之lambda表达式初步认识</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4206982.html">linq之lambda进阶</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4214164.html">linq之隐式类型、自动属性、初始化器、匿名类</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4216256.html">linq之扩展方法</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4222473.html">linq之expression初见</a>

我们可以通过api方式创建表达式树,那么我们有没有办法,将给定的表达式树进行解析,分别得到各个部分呢?答案是肯定,下面看一个例子。

有一个这样的表达式树

可以这样来解析,分别得到各个部分

Linq之Expression进阶
Linq之Expression进阶

输出结果

Linq之Expression进阶

是不是很爽?不知道到这里,你是否对orm框架中,lambda表达式是如何转化为sql语句有那么一点点的灵感?没有没关系,咱们继续看一个例子。如果数据库中有person这样的一个数据表。咱们项目中有对应的person这样的一个持久化类。那么我们创建一个这样的一个查询方法,返回所有龄大于等于18岁的成年人的sql语句。

Linq之Expression进阶
Linq之Expression进阶
Linq之Expression进阶

是不是很方便?传进来一个lambda表达式,就可以通过orm框架内部解析,然后转化为sql语句。也就是通过编写lambda就等于写了sql语句,也不用担心不会写sql语句了。

表达式树应具有永久性。 这意味着如果你想修改某个表达式树,则必须复制该表达式树然后替换其中的节点来创建一个新的表达式树。 

那如何修改呢?

可以通过 expressionvisitor类遍历现有表达式树,并复制它访问的每个节点。

Linq之Expression进阶

一个例子

在项目中添加一个andalsomodifier 类。

将表达式树中的andalse修改为orelse,代码如下:

Linq之Expression进阶
Linq之Expression进阶

测试代码

Linq之Expression进阶
Linq之Expression进阶
Linq之Expression进阶

小结:修改表达式树,需继承expressionvisitor类,并重写它的visitbinary(如果是类似and这类的二元表达式)方法。再举一个例子,如果要将大于修改为小于等于,可修改visitbinary方法的实现。

Linq之Expression进阶
Linq之Expression进阶

 结果

Linq之Expression进阶

expression&lt;tdelegate&gt; 类型提供了 compile 方法以将表达式树表示的代码编译成可执行委托。

还以最上面的那个表达式树为例

 有这样的一个表达式树,现在,我想直接输入一个值,然后得到结果,该如何办呢?可以这样

Linq之Expression进阶
Linq之Expression进阶

1.通过表达式解析,你可以得到表达式树的各个部分。你会发现如果你写的方法的参数是expression&lt;func&lt;t,t&gt;&gt;类型的,你可以更好的使用lambda表达式的特性,操作更方便。例子中,也简单分析了,orm框架中,是如何将lambda表达式解析为sql语句的,也希望能激发你的兴趣。

2.表达式树具有永久性的特性,一经创建,如果你想修改某个表达式树,则必须复制该表达式树然后替换其中的节点来创建一个新的表达式树。具体操作可参考上面的例子。

3.通过complie方法编译后的表达式树,就是一个委托,委托对应的方法的方法体就是表达式树中的lambda表达式,你可以像使用委托一样去使用它。有时你嫌麻烦也可以类似这样直接使用

参考文章

http://msdn.microsoft.com/zh-cn/library/bb397951.aspx

http://msdn.microsoft.com/zh-cn/library/bb546136.aspx

博客地址:

<a href="http://www.cnblogs.com/wolf-sun">http://www.cnblogs.com/wolf-sun/</a>

博客版权:

本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。

如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!

再次感谢您耐心的读完本篇文章。http://www.cnblogs.com/wolf-sun/p/4230226.html