按匿名类型的字段排序

jdp*_*nix 1 c# linq linq-to-objects c#-3.0

我正在使用LINQ to Objects聚合:

  var summary = from esc in objs
                where esc.time.Month == month && esc.time.Year == year
                group esc by esc.rlf_id into g
                select new { 
                  ID = g.Key, 
                  Total = g.Count(), 
                  Preventable = g.Where(a => a.preventable).Count() 
                };
Run Code Online (Sandbox Code Playgroud)

我的查询按预期工作,但我也想按匿名类型中的任意字段对查询进行排序.我找到了LINQ:按匿名类型排序,但是它在VB.NET中并且需要强烈指定要排序的字段.我可以用这个伪代码概念化我想要的东西:

query = get all esc in obj
        aggregate into anonymous type with key ID
          ID = g.Key, Total = g.Count, Preventable = g.Count of preventable
        orderby inputField[0], (optional thenby inputField[1], ..., thenby inputField[n])
Run Code Online (Sandbox Code Playgroud)

我如何完成:

  • 按LINQ查询中的匿名类型字段排序 (完成 - 谢谢Marko!)
  • 通过匿名类型的任意字段进一步排序

我对点语法或查询语法持开放态度.

编辑:有了Marko Stanojevic的回答,我能够部分满足我的要求.我不知道我能够像这样将LINQ方法链接在一起.我现在能够(并获得预期的结果):

var summary = from esc in objs
              where esc.time.Month == month && esc.time.Year == year
              group esc by esc.rlf_id into g
              select new { 
                ID = g.Key, 
                Total = g.Count(), 
                Preventable = g.Where(a => a.preventable).Count() 
              };
summary = summary.OrderBy(e => e.Total); 
Run Code Online (Sandbox Code Playgroud)

我需要的东西可以让我这样做:(伪代码)

summary = summary.<Order/Then>By<(optional)Descending>(e => e.<someUserInput>)
Run Code Online (Sandbox Code Playgroud)

给定一些指定用户想要排序的字符串,显然我可以这样做:

if (sortQuery.Equals("Total", StringComparison.OrdinalIgnoresCase), bool descending) {
  summary = descending ? summary.OrderByDescending(e => e.Total) : summary.OrderBy(e => e.total)
} else if (sortQuery.Equals( /* ... etc */
Run Code Online (Sandbox Code Playgroud)

然而,这最终会变得很丑陋,特别是因为我想将它用于(可能几乎无限的)越来越多的查询.同时还需要考虑到OrderBy()ThenBy().

我希望我正在使用C#4,所以我现在可以使用动态...

Mar*_*vic 5

我不确定是什么问题.计算摘要后,您可以简单地完成

summary = summary.OrderBy(s => s.Total).ToList();
Run Code Online (Sandbox Code Playgroud)

匿名类型的属性立即可见.如果你想传递它并遇到问题,最简单的解决方案是创建一个类,因为你知道它的样子.如果由于某种原因你不想创建自定义类,我想你可以使用Tuple例如:

var summary = from esc in objs
                where esc.time.Month == month && esc.time.Year == year
                group esc by esc.rlf_id into g
                select new Tuple<long, int, int> ( 
                  g.Key, 
                  g.Count(), 
                  g.Where(a => a.preventable).Count() 
                );
Run Code Online (Sandbox Code Playgroud)

然后你可以按.Item1.Item2等排序.不过,我会使用自定义类,因为它更清楚发生了什么.