linq扩展之动态排序
前两天看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扩展之动态排序的更多相关文章
- LINQ中的动态排序
使用Linq动态属性排序 使用反射: public static Func<T,Tkey> DynamicLambda<T, Tkey>(string propertyName ...
- 写一个针对IQueryable<T>的扩展方法支持动态排序
所谓的动态排序是指支持任意字段.任意升序降序的排序.我们希望在客户端按如下格式写: localhost:8000/api/items?sort=titlelocalhost:8000/api/item ...
- linq字符串搜索条件,排序条件-linq动态查询语句 Dynamic LINQ
在做搜索和排序的时候,往往是前台传过来的字符串做条件,参数的数量还不定,这就需要用拼sql语句一样拼linq语句.而linq语句又是强类型的,不能用字符串拼出来. 现在好了,有个开源的linq扩展方法 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(17)-LinQ动态排序
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(17)-LinQ动态排序 首先修复程序中的一个BUG这个BUG在GridPager类中,把sord修改为s ...
- LinQ动态排序
LinQ动态排序 首先修复程序中的一个BUG这个BUG在GridPager类中,把sord修改为sort这个名称填写错误,会导致后台一直无法获取datagrid的排序字段 本来是没有这一讲的,为了使2 ...
- Linq to Sql : 动态构造Expression进行动态查询
原文:Linq to Sql : 动态构造Expression进行动态查询 前一篇在介绍动态查询时,提到一个问题:如何根据用户的输入条件,动态构造这个过滤条件表达式呢?Expression<Fu ...
- ABP框架源码中的Linq扩展方法
文件目录:aspnetboilerplate-dev\aspnetboilerplate-dev\src\Abp\Collections\Extensions\EnumerableExtensions ...
- 通过orderby关键字,LINQ可以实现升序和降序排序。LINQ还支持次要排序。
通过orderby关键字,LINQ可以实现升序和降序排序.LINQ还支持次要排序. LINQ默认的排序是升序排序,如果你想使用降序排序,就要使用descending关键字. static void M ...
- 在Asp .net core 中通过属性映射实现动态排序和数据塑形
目录 属性映射服务实现 动态排序 数据塑形 属性映射服务实现 public class PropertyMappingValue { public IEnumerable<string> ...
随机推荐
- 配置visual studio code进行asp.net core rc2的开发
1.安装.net core sdk https://github.com/dotnet/cli#installers-and-binaries,根据你的系统选择下载. 2.下载vscode的C#扩展插 ...
- Android View中的控件和监听方法...
PS:居然三天没写博客了...今天补上...东西虽多,但是都是一些基础...代码多了一些,有人可能会这样问,粘这么多代码有毛用..其实对于一个Android的初学者来说,一个完整的代码是最容易帮助理解 ...
- Velocity魔法堂系列三:模板与宿主环境通信
一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...
- LeetCode - 41. First Missing Positive
41. First Missing Positive Problem's Link ---------------------------------------------------------- ...
- 网狐6603棋牌游戏源码.rar
网狐6603棋牌游戏源码.rar http://pan.baidu.com/s/1dFgGNq5 网络收集仅供学习,下载后请务必在24小时内删除! 以上是原vc6.0源码,下载后使用vs2015编译, ...
- ASP.NET MVC使用jQuery无刷新上传
昨晚网友有下载了一个jQuery无刷新上传的小功能,他尝试搬至ASP.NET MVC应用程序中去,在上传死活无效果.Insus.NET使用Teamviewer远程桌面,操作一下,果真是有问题.网友是说 ...
- 关于PS激活的一些感想(附上PS CC2015)
最近跟着慕课学了一些前端的必备PS技能,就顺道把PS CC2015装上. 安装的过程没什么大问题,最要命的是激活环节!各种踩坑,但万万没想到,最终我还是成功的把它激活了. 本人所安装PS版本信息 好了 ...
- 【Jquery回顾】解决$冲突的问题->自定义JQuery快捷键
$(function() { $whatever = jQuery.noConflict(); alert($whatever("#cr").text()); })
- Studio for Winforms FlexGrid:导出到 PDF 文件
本篇文章主要介绍如何导出 FlexGrid 到 PDF 格式文件.本文源于论坛用户,有多个用户提出如何把 FlexGrid 导出到 PDF 文件的需求.在这里共享给大家. 当前,ComponentOn ...
- fibonacci数列从a到b的个数
Description 我们定义斐波那契数列如下: f1=1 f2=2 f(n)=f(n-1)+f(n-2)(n>=3) 现在,给定两个数a和b,计算有多少个斐波那契数列中的数在a和b之间( ...