您的位置:首页 > 其它

手工把LINQ转成表达式(一) 基础知识

2011-08-09 14:46 344 查看
LINQ其实并非是全新的概念,在编程语言中内嵌SQL或脚本进行强类型绑定查询很早就存在,LINQ之所以能让人觉得非常强大的地方在于它的设计框架可以让它不仅仅用在数据库查询方面,只要查询对象有IQueryableProvider你就可以通过LINQ去查找。

比如假设有个google的IQueryableProvider,那你只要

from page in Google
where page.Content.Contains("hello world") || page.Keyword == "hello world"
select page;

就能找到关键字包含"hello world"的所有网页,还能进一步做join, group这种操作细化查询结果。

它强大的优势就在于查询语法一致性,不管是何种东西,只要有provider就能用相同的查询语法进行查询,大大简化了查询编程的难度。

而我们这里要研究的不是如何定制一个provider,而是如何把这种查询语法转换成相应的表达式。通过观测IQueryableProvider我们发现

public interface IQueryProvider
{
// Summary:
//     Constructs an System.Linq.IQueryable object that can evaluate the query represented
//     by a specified expression tree.
//
// Parameters:
//   expression:
//     An expression tree that represents a LINQ query.
//
// Returns:
//     An System.Linq.IQueryable that can evaluate the query represented by the
//     specified expression tree.
IQueryable CreateQuery(Expression expression);
//
// Summary:
//     Constructs an System.Linq.IQueryable<T> object that can evaluate the query
//     represented by a specified expression tree.
//
// Parameters:
//   expression:
//     An expression tree that represents a LINQ query.
//
// Type parameters:
//   TElement:
//     The type of the elements of the System.Linq.IQueryable<T> that is returned.
//
// Returns:
//     An System.Linq.IQueryable<T> that can evaluate the query represented by the
//     specified expression tree.
IQueryable<TElement> CreateQuery<TElement>(Expression expression);
//
// Summary:
//     Executes the query represented by a specified expression tree.
//
// Parameters:
//   expression:
//     An expression tree that represents a LINQ query.
//
// Returns:
//     The value that results from executing the specified query.
object Execute(Expression expression);
//
// Summary:
//     Executes the strongly-typed query represented by a specified expression tree.
//
// Parameters:
//   expression:
//     An expression tree that represents a LINQ query.
//
// Type parameters:
//   TResult:
//     The type of the value that results from executing the query.
//
// Returns:
//     The value that results from executing the specified query.
TResult Execute<TResult>(Expression expression);
}

它的2个主要方法CreateQuery和Execute参数都是表达式,而根据提示这个表达式就是代表了LINQ语句,那LINQ语句怎么会变成Expression的呢?这里就是要研究这个。

把LINQ转换成表达式有许多工作要做,首先是我们要有一个能解析LINQ的词法分析器,这里就用之前介绍过的lambda表达式解析/article/11628072.html中修改过的Irony grammar进行LINQ解析;然后是LINQ里会包含大量的表达式也需要解析,正好我们之前已经做完了这部分工作直接用之前的成果就行;最后则是把LINQ关键字转换成相应表达式,这是重点工作后续会一一说明。

当我们有了这个解析器后可以做些什么?我们可以动态运行LINQ!还记得微软C# sample里提供的dynamic query例子么?这个解析器比它更进一步。我们可以用它来合并多个LINQ,也可以用一个LINQ替换掉另一个LINQ的某一部分,我们甚至可以做一个工具让用户直接输入LINQ进行查询就像一些SQL客户端一样方便(当然不用这个解析器你也可以用CodeDOM来实现该相同功能)。

在实现LINQ解析过程中,由于采用了手工硬编码方式来实现表达式转换,所以代码完全是以一种逐句翻译过程写的,整体结构不美观,在这里先给出完整代码,想要直接看代码的可以去http://code.google.com/p/tinynetevent/downloads/list下载ExpressionParser0809.zip。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: