简体   繁体   English

将LINQ顺序查询抽象为多级排序函数

[英]Abstracting LINQ order query to multi level sort function

I would like to make a sorting extension method which will take a Generic Collection and sort it using one or more keys. 我想制作一个排序扩展方法,它将采用Generic Collection并使用一个或多个键对其进行排序。 The keys will be properties of the collection's containing objects. 键将是包含对象的集合的属性。

A sample LINQ query with 3 keys looks like this. 带有3个键的示例LINQ查询如下所示。

studentResults.OrderBy(x => x.CG).ThenBy(x => x.Student.Roll)
                                    .ThenBy(x => x.Student.Name).ToList();

I have already found something which can do this with one key. 我已经找到了一些可以用一把钥匙做到这一点的东西。

public static List<TSource> OrderByAsListOrNull<TSource, TKey>(
        this ICollection<TSource> collection, Func<TSource,TKey> keySelector)
    {

        if (collection != null && collection.Count > 0) {
            return collection
                .OrderBy(x => keySelector(x))
                .ToList();
        }
        return null;
    }

I thought of using IEnumerable<Func<TSource, TKey> keySelector> , but I cannot call the function like that. 我想过使用IEnumerable<Func<TSource, TKey> keySelector> ,但我无法像这样调用函数。

So, how may I implement a method of this kind? 那么,我该如何实现这种方法呢?

In theory, you could build a multi-levelled sort extension, which diffentiates between the initial OrderBy and the subsequent ThenBy s for secondary, tertiary sorting tiebreakers. 理论上,你可以构建一个多级排序扩展,它在初始OrderBy和后续的ThenBy之间进行ThenBy用于二级,三级排序的破坏者。 Since by taking multiple order functions, each of which could reference a different type, you'll need to soften the projected type (I've used object , below). 由于通过采用多个顺序函数,每个函数可以引用不同的类型,您需要软化投影类型(我在下面使用了object )。

public static class Extensions
{
    public static IEnumerable<T> MyOrderBy<T>(
        this IEnumerable<T> source, 
        params Func<T, object>[] orders)
    {
        Debug.Assert(orders.Length > 0);
        var sortQuery = source.OrderBy(orders[0]);
        foreach(var order in orders.Skip(1))
        {
            sortQuery = sortQuery.ThenBy(order);
        }
        return sortQuery;
    }
}

public class Poco
{
    public string Name {get; set;}
    public int Number {get; set;}
}


void Main()
{
    var items = new []{
        new Poco{Name = "Zebra", Number = 99}, 
        new Poco{Name = "Apple", Number = 123}};

    foreach(var poco in items.MyOrderBy(i => i.Number, i => i.Name))
    {
        Console.WriteLine(poco.Name);
    }
}

The problem with this (as with your original function) is that you'll probably want to order by descending at some point. 这个问题(与你的原始函数一样)是你可能想要通过降序来订购。 Although for numeric sort functions this could be hacked by passing a *-1, it's going to be really difficult to do this for an arbitrary type 虽然对于数字排序函数,这可以通过传递* -1来攻击,但对于任意类型来说这将是非常困难的

// Hack : Order a numeric descending
item => item.Number * -1

For me, I would just stay with Linq's sorting extensions, and not try to abstract them in any way! 对我来说,我会留在Linq的排序扩展中,而不是试图以任何方式抽象它们!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM