zoukankan      html  css  js  c++  java
  • 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了
  • 相关阅读:
    Python中所有的关键字
    关于selenium的8种元素定位
    对提示框的操作
    selenium+webservice进行百度登录
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled...报错解决
    Vue中使用echarts
    npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142解决方法
    插入排序
    冒泡排序优化
    roject 'org.springframework.boot:spring-boot-starter-parent:XXX' not found 解决
  • 原文地址:https://www.cnblogs.com/woaic/p/3942921.html
Copyright © 2011-2022 走看看