前两天看QQ群里面,一位朋友问的问题,说在linq中怎么实现动态排序呢,自己想了半天,没有头绪,网上找了下相关的资料,看了下,收益挺多,记录下来。

之前我们没有如果不知道动态排序的方法的话,我们可能会这样写

[code lang="csharp"]
case SortFields.Price:
if (rules == SortRules.ESC)
{
result = result.OrderBy(s => s.Price);
}
else
{
result = result.OrderByDescending(s => s.Price);
}
break;
case SortFields.BuyDate:
if (rules == SortRules.ESC)
{
result = result.OrderBy(s => s.BuyDate);
}
else
{
result = result.OrderByDescending(s => s.BuyDate);
}
break;
[/code]

这种代码,我们看起来极其繁琐,绝对是个体力活。。。
通过百度,我看到博客园的一篇文章,突然在黑夜中看到了光明
http://www.cnblogs.com/126/archive/2007/09/09/887723.html
根据这篇文章的讲解,我们可以看到:
Linq To Sql支持用户动态生成lambda表达式,作者通过自定义的方法,传一个实体对象过去,根据判断每个字段的值是否为null,来进行动态生成lambda表达式。
基本原理懂了,下面就剩写代码了。
由于老外已经有这方面的经验,已经写出现成的helper,我这边就不造车轮了。
直接贴老外的代码:
[code lang="csharp"]
/***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is LINQExtensions.StringFieldNameSortingSupport.
*
* The Initial Developer of the Original Code is
* Davy Landman.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace LINQExtensions
{
public static class StringFieldNameSortingSupport
{
#region Private expression tree helpers

private static LambdaExpression GenerateSelector<TEntity>(String propertyName, out Type resultType) where TEntity : class
{
// Create a parameter to pass into the Lambda expression (Entity => Entity.OrderByField).
var parameter = Expression.Parameter(typeof(TEntity), "Entity");
// create the selector part, but support child properties
PropertyInfo property;
Expression propertyAccess;
if (propertyName.Contains('.'))
{
// support to be sorted on child fields.
String[] childProperties = propertyName.Split('.');
property = typeof(TEntity).GetProperty(childProperties[0]);
propertyAccess = Expression.MakeMemberAccess(parameter, property);
for (int i = 1; i < childProperties.Length; i++)
{
property = property.PropertyType.GetProperty(childProperties[i]);
propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
}
}
else
{
property = typeof(TEntity).GetProperty(propertyName);
propertyAccess = Expression.MakeMemberAccess(parameter, property);
}
resultType = property.PropertyType;
// Create the order by expression.
return Expression.Lambda(propertyAccess, parameter);
}
private static MethodCallExpression GenerateMethodCall<TEntity>(IQueryable<TEntity> source, string methodName, String fieldName) where TEntity : class
{
Type type = typeof(TEntity);
Type selectorResultType;
LambdaExpression selector = GenerateSelector<TEntity>(fieldName, out selectorResultType);
MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName,
new Type[] { type, selectorResultType },
source.Expression, Expression.Quote(selector));
return resultExp;
}
#endregion
public static IOrderedQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string fieldName) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "OrderBy", fieldName);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}

public static IOrderedQueryable<TEntity> OrderByDescending<TEntity>(this IQueryable<TEntity> source, string fieldName) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "OrderByDescending", fieldName);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
public static IOrderedQueryable<TEntity> ThenBy<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "ThenBy", fieldName);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
public static IOrderedQueryable<TEntity> ThenByDescending<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "ThenByDescending", fieldName);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
public static IOrderedQueryable<TEntity> OrderUsingSortExpression<TEntity>(this IQueryable<TEntity> source, string sortExpression) where TEntity : class
{
String[] orderFields = sortExpression.Split(',');
IOrderedQueryable<TEntity> result = null;
for (int currentFieldIndex = 0; currentFieldIndex < orderFields.Length; currentFieldIndex++)
{
String[] expressionPart = orderFields[currentFieldIndex].Trim().Split(' ');
String sortField = expressionPart[0];
Boolean sortDescending = (expressionPart.Length == 2) && (expressionPart[1].Equals("DESC", StringComparison.OrdinalIgnoreCase));
if (sortDescending)
{
result = currentFieldIndex == 0 ? source.OrderByDescending(sortField) : result.ThenByDescending(sortField);
}
else
{
result = currentFieldIndex == 0 ? source.OrderBy(sortField) : result.ThenBy(sortField);
}
}
return result;
}
}
}
[/code]

使用方法:
查看代码中的:
OrderUsingSortExpression这个方法,这个方法就是使用方法,按照上面的传参就ok了

linq扩展之动态排序的更多相关文章

  1. LINQ中的动态排序

    使用Linq动态属性排序 使用反射: public static Func<T,Tkey> DynamicLambda<T, Tkey>(string propertyName ...

  2. 写一个针对IQueryable<T>的扩展方法支持动态排序

    所谓的动态排序是指支持任意字段.任意升序降序的排序.我们希望在客户端按如下格式写: localhost:8000/api/items?sort=titlelocalhost:8000/api/item ...

  3. linq字符串搜索条件,排序条件-linq动态查询语句 Dynamic LINQ

    在做搜索和排序的时候,往往是前台传过来的字符串做条件,参数的数量还不定,这就需要用拼sql语句一样拼linq语句.而linq语句又是强类型的,不能用字符串拼出来. 现在好了,有个开源的linq扩展方法 ...

  4. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(17)-LinQ动态排序

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(17)-LinQ动态排序 首先修复程序中的一个BUG这个BUG在GridPager类中,把sord修改为s ...

  5. LinQ动态排序

    LinQ动态排序 首先修复程序中的一个BUG这个BUG在GridPager类中,把sord修改为sort这个名称填写错误,会导致后台一直无法获取datagrid的排序字段 本来是没有这一讲的,为了使2 ...

  6. Linq to Sql : 动态构造Expression进行动态查询

    原文:Linq to Sql : 动态构造Expression进行动态查询 前一篇在介绍动态查询时,提到一个问题:如何根据用户的输入条件,动态构造这个过滤条件表达式呢?Expression<Fu ...

  7. ABP框架源码中的Linq扩展方法

    文件目录:aspnetboilerplate-dev\aspnetboilerplate-dev\src\Abp\Collections\Extensions\EnumerableExtensions ...

  8. 通过orderby关键字,LINQ可以实现升序和降序排序。LINQ还支持次要排序。

    通过orderby关键字,LINQ可以实现升序和降序排序.LINQ还支持次要排序. LINQ默认的排序是升序排序,如果你想使用降序排序,就要使用descending关键字. static void M ...

  9. 在Asp .net core 中通过属性映射实现动态排序和数据塑形

    目录 属性映射服务实现 动态排序 数据塑形 属性映射服务实现 public class PropertyMappingValue { public IEnumerable<string> ...

随机推荐

  1. Git 版本管理

    应用情景1:添加文件(单个.多个.目录)到Git版本库,提交一个版本快照. 应用情景2:穿越历史回到过去,版本回退,从当前版本回退到之前提交过的某个版本上. 应用情景3:穿越历史过头了,版本回退多了, ...

  2. NopCommerce之任务执行

    NOP任务提供两种:手动执行(立即)和定时执行两种. 首先来说下手动任务执行过程,下图是NOP定时任务管理界面: 从上面可以看出,我们可以选择具体的任务来手动执行任务(立即执行),当点击[立即执行]按 ...

  3. C++的最佳特性(译)

    最近看到了很多优秀的文章,包括<Why mobile web apps are slow>,实在忍不住翻译出来跟大家分享.这篇文章通过大量的实验和参考文献向我们说明移动应用开发所遇到的问题 ...

  4. 使用Kibana 分析Nginx 日志并在 Dashboard上展示

    一.Kibana之Visualize 功能 在首页上Visualize 标签页用来设计可视化图形.你可以保存之前在discovery中的搜索来进行画图,然后保存该visualize,或者加载合并到 d ...

  5. Vim杂记:markdown插件

    一.安装插件 从以下地址下载压缩包 github下载:https://github.com/plasticboy/vim-markdown plasticboy下载:http://plasticboy ...

  6. Eclipse启动报错:A java runtime Environment(JRE) or java Development……的解决办法

    第一种: 解决方法: 系统变量里设置下面: 变量名:JAVA_HOME 变量值:D:\Java\jdk1.8.0_31 变量名:CLASSPATH 变量值:.;%JAVA_HOME%\lib; 变量名 ...

  7. 循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

  8. 使用HttpRequester模拟发送及接收Json请求

    1.开发人员在火狐浏览器里经常使用的工具有Firebug,httprequester,restclient......火狐浏览器有一些强大的插件供开发人员使用!需要的可以在附加组件中扩展. 2.htt ...

  9. C#接口知识大全收藏

    第一节 接口慨述 接口(interface)用来定义一种程序的协定.实现接口的类或者结构要与接口的定义严格一致.有了这个协定,就可以抛开编程语言的限制(理论上).接口可以从多个基接口继承,而类或结构可 ...

  10. jQquery.validate自定义规则的使用案例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...