废话不多说,我们直接看一个demo:输出PageCount大于等于100页的所有Book的标题。
标准方法:
var books = from book in SampleData.Books where book.PageCount >= 100 select book; foreach (var book in books) { Console.WriteLine(book.Title); }
输出结果:
这段代码很简单,首先检索所有pageCount大于等100的书籍,然后遍历检索的结果,输出他们的书名。但是现在我有个需求,能不能在Linq query expression中直接输出书籍的标题呢?很可惜,Linq没有为我们提供这样的query operation或query expression。但是这里我们可以自己写方法,那么接下来我就跟大家一起来实现这样一个功能的扩展方法。
添加扩展方法:
大家有没有考虑这个方法应该添加到什么地方呢?能不能适用于所有的实体对象呢?假如我下次检索的不是Book,而是Student或者Product之类的呢?综合上述原因,我考虑把这个方法添加到System.Linq命名空间下面的Enumerable类中,作为它的扩展方法。
那么我们就来些这样的一个扩展方法,实现扩展方法的三要素大家应该都很清楚了,static class 、static method、this keyword。
我们在项目中添加一个IEnumerableExt类:
using System; using System.Collections.Generic; using System.Linq; using System.Text; //注意:这里一定要设置为System.Linq命名空间 namespace System.Linq { //指定扩展方法要添加的类名 public static class Enumerable { /// <summary> /// 扩展方法,遍历collection,并将每个element作为参数传到func方法里面 /// </summary> /// <typeparam name="T">entity类型</typeparam> /// <param name="source">origin sequence</param> /// <param name="func">处理函数</param> public static void ForEach<T>(this IEnumerable<T> source, Action<T> func) { foreach (var item in source) { //实现某种功能的方法,我们这里用到的是输出book.Title func(item); } } } }
接下来我们就改善我们一开始的那个demo:我们让query expression中实现foreach中实现的功能:
(from book in SampleData.Books where book.PageCount >= 100 select book) .ForEach(book => Console.WriteLine(book.Title));
输出结果:
就是这么简单,得到的结果和第一步完全相同,但是代码量明显减少,而且我们编写的扩展方法可以重复利用。那么接下来,我就实现Mulltiple Foreach Expression。
在每个Title后面都加上一段话:
SampleData.Books .Where(book => book.PageCount >= 100) .Select(book => book) .ForEach(book => { book.Title += " (long)"; Console.WriteLine(book.Title); });
输出结果:
小结:利用Linq Design Pattern 可以非常有效的进行代码复用,而且灵活性提高并且减少代码量。大家为何不用呢?