如何在Linq中的一行代码中对多个属性的列表进行排序

时间:2016-04-08 00:20:25

标签: c# linq sorting

我想在多个属性上对列表进行排序。我知道我可以使用

List<Order> l = source.OrderBy(c=> c.Property1).ThenBy(c=> c.Property2).ToList();

但是,它仅用于提升。如果我想对列表进行降序排序,我需要另一个代码

List<Order> l = source.OrderByDescending(c=> c.Property1).ThenByDescending(c=> c.Property2).ToList();

如果我想将property1排序为升序而将property2排序为降序,我必须使用

List<Order> l = source.OrderBy(c=> c.Property1).ThenByDescending(c=> c.Property2).ToList();

对于2个属性的排序,我需要4个不同的代码,在3个属性上,我需要9个不同的代码。没有好处。我想知道是否有办法在一个代码中进行排序。谢谢。

3 个答案:

答案 0 :(得分:1)

您可以编写自己的LINQ扩展来确定要选择的方法。例如:

public static class LinqExtensions
{
    public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, bool ascending)
    {
        return ascending ? source.OrderBy(keySelector) : source.OrderByDescending(keySelector);
    }
}

然后你可以像这样使用它:

source.OrderBy(a => a.Id, ascending);

答案 1 :(得分:1)

正如我在评论中提到的,你可以创建这样的东西......

public static class LinqExtension
{
    public static IOrderedEnumerable<TSource> OrderByAsc<TSource, TKey>(
    this IEnumerable<TSource> source,
    Expression<Func<T, object>> expression)
    {
        IEnumerable<TSource> newEnumerable = source;
        int ctr = 0;
        NewArrayExpression array = expression.Body as NewArrayExpression;
        foreach( object obj in ( IEnumerable<object> )( array.Expressions ) )
        {
             if(ctr == 0)
             newEnumerable = newEnumerable
                .OrderBy(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
             else
             newEnumerable = newEnumerable
                .ThenBy(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
             ctr++;
        }

        return newEnumerable;      
    }

    public static IOrderedEnumerable<TSource> OrderByDesc<TSource, TKey>(
    this IEnumerable<TSource> source,
    Expression<Func<T, object>> expression)
    {
        IEnumerable<TSource> newEnumerable = source;

        NewArrayExpression array = expression.Body as NewArrayExpression;
        int ctr = 0;
        foreach( object obj in ( IEnumerable<object> )( array.Expressions ) )
        {
             if(ctr == 0)
             newEnumerable = newEnumerable
                .OrderByDescending(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
             else
             newEnumerable = newEnumerable
                .ThenByDescending(item => item.GetType().GetProperty(obj.ToString()).GetValue(item, null));
             ctr++;
        }

        return newEnumerable;      
    } 
}

并像这样使用它:

using myNameSpace.LinqExtensions;
...

l = l.OrderByAsc(item => new [] { item.Prop1, item.Prop2, item.Prop3});
l = l.OrderByDesc(item => new [] { item.Prop1, item.Prop2, item.Prop3});

当然,您可以尝试创建一个扩展,通过升序和降序将两个顺序组合成一个方法。只是一个想法。

免责声明:我在记事本上写了这封信,由于资源不足,我们没有对其进行过测试。

答案 2 :(得分:0)

System.Linq.Dynamic包提供了一个OrderBy扩展方法,它只接受一个字符串:

using System.Linq.Dynamic;
//...    

var l = source.OrderBy("Property1 ascending, Property2 descending").ToList();

您可以使用它来动态构建精美的表达式:

string orderByClause = string.Format("Property1 {0}, Property2 {1}", "ascending", "descending");
var l = source.OrderBy(orderByClause).ToList();

有关项目Wiki

中的更多信息,请参阅IQueryable Extension Methods