我想制作一个排序扩展方法,它将采用Generic Collection并使用一个或多个键对其进行排序。键将是包含对象的集合的属性。
带有3个键的LINQ查询示例如下所示。
studentResults.OrderBy(x => x.CG).ThenBy(x => x.Student.Roll)
.ThenBy(x => x.Student.Name).ToList();
我已经找到了一些可以用一把钥匙做的事情。
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;
}
我想过使用IEnumerable<Func<TSource, TKey> keySelector>
,但我无法像这样调用函数。
那么,我该如何实现这种方法?
答案 0 :(得分:3)
理论上,你可以构建一个多级排序扩展,它在初级OrderBy
和后续ThenBy
之间进行区分,用于二级,三级排序的破坏者。由于通过采用多个订单函数,每个函数都可以引用不同的类型,您需要软化投影类型(我在下面使用过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);
}
}
这个问题(与你原来的功能一样)是你可能想要通过某种程度的降序来订购。虽然对于数字排序函数,这可以通过传递* -1来攻击,但对于任意类型来说这很难做到这一点
// Hack : Order a numeric descending
item => item.Number * -1
对我来说,我会留在Linq的排序扩展中,而不是试图以任何方式抽象它们!