将 LINQ 订单查询抽象为多级排序函数
Abstracting LINQ order query to multi level sort function
我想制作一个排序扩展方法,它将采用通用集合并使用一个或多个键对其进行排序。键将是集合包含对象的属性。
具有 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>
,但我不能那样调用函数。
那么,我该如何实现这种方法呢?
理论上,您可以构建一个 multi-levelled 排序扩展,它区分初始 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 的排序扩展,而不是尝试以任何方式抽象它们!
我想制作一个排序扩展方法,它将采用通用集合并使用一个或多个键对其进行排序。键将是集合包含对象的属性。
具有 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>
,但我不能那样调用函数。
那么,我该如何实现这种方法呢?
理论上,您可以构建一个 multi-levelled 排序扩展,它区分初始 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 的排序扩展,而不是尝试以任何方式抽象它们!