使用 Linq.Expressions.Expression 排序

Posted

技术标签:

【中文标题】使用 Linq.Expressions.Expression 排序【英文标题】:Sort using Linq.Expressions.Expression 【发布时间】:2012-08-30 07:54:01 【问题描述】:

我编写的这段代码按sortColumn 列对IQueryable<T> 进行排序。我想扩展它,以便将列 BirthDate 的值等于 DateTime.Today 的条目放在排序的首位,但我就是找不到或想不出如何完成这项工作。

public static IQueryable<T> OrderByField<T>(this IQueryable<T> q, string sortColumn, bool asc)

    var param = Expression.Parameter(typeof(T), "p");

    var prop = Expression.Property(param, sortColumn);

    var exp = Expression.Lambda(prop, param);

    string method = asc ? "OrderBy" : "OrderByDescending";

    Type[] types = new[]  q.ElementType, exp.Body.Type ;

    var mce = Expression.Call(typeof(Queryable), method, types, q.Expression, exp);

    return q.Provider.CreateQuery<T>(mce);

【问题讨论】:

见:***.com/questions/298725/multiple-order-by-in-linq 这可行,但我无法使用参数“sortColumn”对所需的任何列进行排序,除非我使用大量 if()s。 首先,您不应该在这里返回IOrderedQueryable 吗?其次,您不能创建另一个扩展 IOrderedQueryable 而不是使用 ThenByThenByDescending 作为 Queryable 方法的 IQueryable 的副本吗? 【参考方案1】:

见Handle GridView.OnSorting() and create sorting expression dynamically using LINQ

public static class SortExpressionBuilder<T>

    private static IDictionary<SortDirection, ISortExpression> directions =  new Dictionary<SortDirection, ISortExpression>
    
         SortDirection.Ascending, new OrderByAscendingSortExpression() ,
         SortDirection.Descending, new OrderByDescendingSortExpression() 
    ;

    interface ISortExpression
    
        Func<IEnumerable<T>, Func<T, object>, IEnumerable<T>> GetExpression();
    

    class OrderByAscendingSortExpression : ISortExpression
    
        public Func<IEnumerable<T>, Func<T, object>, IEnumerable<T>> GetExpression()
        
            return (c, f) => c.OrderBy(f);
        
    

    class OrderByDescendingSortExpression : ISortExpression
    
        public Func<IEnumerable<T>, Func<T, object>, IEnumerable<T>> GetExpression()
        
            return (c, f) => c.OrderByDescending(f);
        
    

    public static Func<IEnumerable<T>, Func<T, object>, IEnumerable<T>> CreateExpression(SortDirection direction)
    
        return directions[direction].GetExpression();
    


public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> collection, string columnName, SortDirection direction)

    ParameterExpression param = Expression.Parameter(typeof(T), "x"); // x
    Expression property = Expression.Property(param, columnName);     // x.ColumnName
    Func<T, object> func = Expression.Lambda<Func<T, object>>(        // x => x.ColumnName
       Expression.Convert(Expression.Property(param, columnName), 
       typeof(object)), param
    ).Compile();

    Func<IEnumerable<T>, Func<T, object>, IEnumerable<T>> expression = SortExpressionBuilder<T>.CreateExpression(direction);
    IEnumerable<T> sorted = expression(collection, func);
    return sorted;

以及底部的链接:

Sorting a list using Lambda/Linq to objects GridView sorting: SortDirection always Ascending

【讨论】:

【参考方案2】:

您可以尝试对类似于以下表达式的内容进行排序:

.OrderBy(x => BirthDate == DateTime.Now.Date ? 0 : 1).ThenBy(sortColumn);

【讨论】:

以上是关于使用 Linq.Expressions.Expression 排序的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)