打造自己的LINQ Provider(中):IQueryable和IQueryProvider
[2] IEnumerable
[3] IQueryable
[4] IQueryProvider接口
[5] 扩展LINQ的两种方式
[6] 总结
概述
在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHibernate、LINQ to Google等,大有“一切皆LINQ”的趋势。LINQ本身也提供了很好的扩展性,使得我们可以轻松的编写属于自己的LINQ Provider。
本文为打造自己的LINQ Provider系列文章第二篇,主要详细介绍自定义LINQ Provider中两个最重要的接口IQueryable和IQueryProvider。
IEnumerable<T>接口
在上一篇打造自己的LINQ Provider(上):Expression Tree揭秘》一文的最后,我说到了这样一句话:需要注意的是LINQ to Objects并不需要任何特定的LINQ Provider,因为它并不翻译为表达式目录树,带着这个问题,我们先来看下面这段代码,查询的结果query为IEnumerable<String>类型:
static void Main(string[] args) { List<String> myList = new List<String>() { "a", "ab", "cd", "bd" }; IEnumerable<String> query = from s in myList where s.StartsWith("a") select s; foreach (String s in query) { Console.WriteLine(s); } Console.Read(); }
这里将返回两条结果,如下图所示:
这里就有一个问题,为什么在LINQ to Objects中返回的是IEnumerable<T>类型的数据而不是IQueryable<T>呢?答案就在本文的开始,在LINQ to Objects中查询表达式或者Lambda表达式并不翻译为表达式目录树,因为LINQ to Objects查询的都是实现了IEnmerable<T>接口的数据,所以查询表达式或者Lambda表达式都可以直接转换为.NET代码来执行,无需再经过转换为表达式目录这一步,这也是LINQ to Objects比较特殊的地方,它不需要特定的LINQ Provider。我们可以看一下IEnumerable<T>接口的实现,它里面并没有Expression和Provider这样的属性,如下图所示: