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> ...
随机推荐
- Keepalived 使用指南
Keepalived 使用指南 1. 简介 负载均衡是虚拟服务的一种好的处理方案.当设计一种负载均衡的拓扑时一定要考虑到如下两点: 真实服务器的可用性使用健康检测机制. 负载均衡器的可用性使用故 ...
- 3 Servlet监听器
作者:禅楼望月(http://www.cnblogs.com/yaoyinglong) 1. ServletConfig和ServletContext 1.1 ServletConfig和Servle ...
- (非妙味3):浏览器window事件:及浏览各种尺寸介绍
(触发)window.onload; window.onscroll; window.onresize; (兼容)网页可视区尺寸.网页全文尺寸.滚动距离 (实例)广告块高度动态居中.回到顶部 ...
- Android 学习笔记之Volley(六)实现获取服务器的字符串响应...
学习内容: 1.使用StringRequest实现获取服务器的字符串响应... 前几篇一直都在对服务——响应过程的源码进行分析,解析了整个过程,那么Volley中到底实现了哪些请求才是我们在开发中 ...
- CentOS6.5菜鸟之旅:文件权限详解
一.前言 Linux下所有资源.设备均被视作文件来操作,而文件权限则是决定用户可各文件操作的范围,无论是平时使用Linux,还是写程序均涉及这方面.以下为个人学习的整理,供以后查阅. 二. 三种权限 ...
- 面向对象的Javascript(4):重载
在小项目中对于JavaScript使用,只要写几个function就行了.但在大型项目中,尤其是在开发追求 良好的用户体验的网站中,如SNS,就会 用到大量的JavaScrpt,有时JavaScrip ...
- [CLR via C#]13. 接口
一.类和接口继承 在Microsoft.Net Framwork中,有一个名为System.Object的类,它定义了4个公共实例方法:ToString, Equals, GetHashCode和Ge ...
- NopCommerce中的单例
项目中经常会遇到单例的情况.大部分的单例代码都差不多像这样定义: internal class SingletonOne { private static SingletonOne _singleto ...
- 轻松解决MYSQL数据库连接过多的错误
1.数据库系统允许的最大可连接数max_connections.这个参数是可以设置的.如果不设置,默认是100.最大是16384. 2.数据库当前的连接线程数threads_connected.这是动 ...
- [moka同学笔记]yii2.0小物件的简单使用(第一种方法)
这是第一种方法,还有另一种方法,其实都差不多. 1.在创建widgets\HelloWiget.php <?php /** * Created by PhpStorm. * User: Admi ...