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了
  • 相关阅读:
    react获取ref的几种形式
    vue与react的小区别
    vue当中计算属性重新计算依赖关系
    移动端常见问题
    WX小程序--开发中相关问题记录
    ECMAScript6 入门 Set 和Map结构
    ECMAScript6 入门 Class 的基本语法与继承
    ECMAScript6 入门 Generator
    ECMAScript6 入门 Promise
    ECMAScript6 入门 Symbol
  • 原文地址:https://www.cnblogs.com/woaic/p/3942921.html
Copyright © 2011-2022 走看看