轻轻松松学习Linq排序

Linq排序在一系列Linq操作中应该使用频率***的,关于Linq排序的文章也很多,但是笔者的这篇文章最值得一读了,因为他把理论与实践结合的十分***,理解起来也很简单,希望能给你带来帮助。

阿荣网站制作公司哪家好,找成都创新互联公司!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设等网站项目制作,到程序开发,运营维护。成都创新互联公司公司2013年成立到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联公司

在程序开发中,对数据进行排序是很常见的操作。现在就来演示一下Linq排序,假设现在有一个类Customer,定义如下所示:

 
 
 
  1. public class Customer
  2. {
  3. public string Id { get; set; }
  4. public string Name { get; set; }
  5. public decimal Age { get; set; }
  6. }

我们现在要对很多Customer对象进行排序,最简单的就是使用Linq排序的orderby子句:

 
 
 
  1. from c in Customers orderby c.Id select c;

上面实现了按照Id来进行Linq排序。可是需求变了,用户现在想用Name来排序。好办!把上面的改一改比如下面这样就可以了:

 
 
 
  1. from c in Customers orderby c.Name select c;

可是需求又变了,用户现在说,你在程序中不能写死,得列一个菜单,我点哪个你就按哪个给我Linq排序。这个也不难办:

 
 
 
  1. var searchResult = from c in Customers select c;
  2. if (columnName == "Id")
  3. {
  4. searchResult = from c in Customers orderby c.Id select c;
  5. }
  6. else if (columnName == "Name")
  7. {
  8. searchResult = from c in Customers orderby c.Id select c;
  9. }
  10. else ...

这确实解决了问题,可是这样的代码不易维护。如果加属性了怎么办?如果属性改名字了怎么办?如果有好多的不同的类都需要这样的Linq排序怎么办?

下面我介绍一种较为通用的解决方案,此方案的核心技术是反射(Reflection)和扩展方法(Extension Methods)。

 
 
 
  1. public static IOrderedQueryable  OrderBy (  
  2. this IQueryable  source,  
  3. Expression > keySelector,  
  4. IComparer  comparer  
  5. )

参数source是一个用来排序的对象,keySelector是用来取出用来Linq排序的键的函数,comparer(比较器)用来比较取出的两个键值。

对象的属性类型可能多种多样,而我们又不想为每种类型分别指定comparer(因为那样做的话也将是一堆if else…)。变通一下思路,不管遇到哪种类型的属性,我们都先把它的值放到一个共同的容器中,然后为这个容器写一个comparer类。我们把类型判断留到了这个comparer中,因为类型是有限的,至少我们需要处理的那些属性的类型是有限的。
上面提到的这个值的容器也是一个类,定义如下:

 
 
 
  1. public class CommonComparableValue
  2. {
  3. public object RealValue { get; set; }
  4. }

相应的比较类定义如下:

 
 
 
  1. public class CommonComparableValueComparer : IComparer  
  2. {
  3. public int Compare(CommonComparableValue x, CommonComparableValue y)
  4. {
  5. string s = x.RealValue as string;
  6. if (s != null)
  7. {
  8. return s.CompareTo(y.RealValue);
  9. }
  10. int? i = x.RealValue as int?;
  11. if (i != null)
  12. {
  13. return i.Value - (int)y.RealValue;
  14. }
  15. decimal? d = x.RealValue as decimal?;
  16. if (d != null)
  17. {
  18. return d.Value.CompareTo((decimal)y.RealValue);
  19. }
  20. throw new NotImplementedException("NotImplemented Data Type!!!");
  21. }
  22. }

这里的比较类只用到了int,string等几种类型,如果属性有其它的类型,也应该在这里添加。从代码实现可以看出,即使属性的类型是复杂数据类型也可以这么处理。

现在来看keySelector的实现。它是用来取出待比较的属性值的函数。这个函数应该是这个样子的:

 
 
 
  1. public delegate TResult Func  
  2. ( T  arg )

在这里,T的类型就是Customer,TResult就是刚刚已经那个存放任意属性类型的值的容器CommonComparableValue。

在这个实现取键值的函数里,我们只有一个Customer类型的参数arg可用,而那个用来Linq排序的属性名字是在运行期间确定的,如何才能取出我们想要的属性的值呢?方法是这样的,先通过扩展方法为Customer加一个名为GetSortingKeyValue的取键值方法,代码如下:

 
 
 
  1. public static class CustomerSortExtension
  2. {
  3. public static CommonComparableValue GetSortingKeyValue(this Customer ainfo, string columnName)
  4. {
  5. Type t = ainfo.GetType();
  6. PropertyInfo pinfo = t.GetProperty(columnName);
  7. if (pinfo == null)
  8. {
  9. throw new Exception("Property " + columnName + "not found");
  10. }
  11. else
  12. {
  13. return new CommonComparableValue
  14. {
  15. RealValue = pinfo.GetValue(ainfo, null)
  16. };
  17. }
  18. }
  19. }

这里就是通过一个字符串获取属性值,核心是反射。接下来只要在那个keySelector方法中调用GetSortingKeyValue方法就可以了。

到这里,各种准备活动就做完了。现在来看一下怎么把这些东西组织起来实现Linq排序:

 
 
 
  1. var searchResult = from c in Customers select c;
  2. Func  myFunc = x => x.GetSortingKeyValue(columnName);  
  3. CommonComparableValueComparer comparer = new CommonComparableValueComparer();
  4. searchResult = searchResult.OrderBy(myFunc, comparer);

这种方案的主要内容到这里就介绍完了。

***提一下,如果你想把这些东西用到你的代码中,你一般需要做的只有:将扩展方法的***个参数改为你需要Linq排序的那个类型。比如要为Person排序,扩展方法则可以是这个样子:

 
 
 
  1. public static CommonComparableValue GetSortingKeyValue(this Customer ainfo, string columnName)

当然,那个CommonComparableValueComparer类也应该根据实际类型修改以支持更多的属性类型。

以上就是对Linq排序的详细介绍,从理论到方法,很有价值的一篇文章呦!

本文标题:轻轻松松学习Linq排序
浏览路径:http://www.shufengxianlan.com/qtweb/news15/230465.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联