c# - 动态创建 GroupBy 语句

标签 c# linq

我正在尝试动态重组一些数据以在 TreeView 中显示,这将允许用户最多选择以下三个维度来对数据进行分组:

Organisation
Company
Site
Division
Department

因此,例如,如果用户选择他们想要按公司分组,然后按网站分组,然后按部门...以下代码将执行所需的分组。

var entities = orgEntities
// Grouping Level 1
.GroupBy(o => new { o.CompanyID, o.CompanyName })
.Select(grp1 => new TreeViewItem
        {
        CompanyID = grp1.Key.CompanyID,
        DisplayName = grp1.Key.CompanyName,
        ItemTypeEnum = TreeViewItemType.Company,
        SubItems = grp1
               // Grouping Level 2
               .GroupBy(o => new { o.SiteID, o.SiteName })
               .Select(grp2 => new TreeViewItem
               {
               SiteID = grp2.Key.SiteID,
               DisplayName = grp2.Key.SiteName,
               ItemTypeEnum = TreeViewItemType.Site,
               SubItems = grp2
                  // Grouping Level 3
                  .GroupBy(o => new { o.Division })
                  .Select(grp3 => new TreeViewItem
                  {
                      DisplayName = grp3.Key.Division,
                      ItemTypeEnum = TreeViewItemType.Division,
                  }).ToList()
               }).ToList()
        })
.ToList();

这会给出这样的结构:

+ Company A
  + Site A
    + Division 1
    + Division 2
  + Site B
    + Division 1
+ Company B
  + Site C
    + Division 2
+ Company C
  + Site D

但是,这只为我提供了大量组合中的一个。

我如何将其转换成可以根据用户选择的三个维度动态创建等效表达式的东西,这样我就不必为每个组合创建这些表达式中的每一个!!?

谢谢你们。

最佳答案

一个有趣的问题。为键分组选择一种类型,为结果选择另一种类型...使得很可能得到您想要的。

public struct EntityGroupKey
{
  public int ID {get;set;}
  public string Name {get;set;}
}

public class EntityGrouper
{
  public Func<Entity, EntityGroupKey> KeySelector {get;set;}
  public Func<EntityGroupKey, TreeViewItem> ResultSelector {get;set;}
  public EntityGrouper NextGrouping {get;set;} //null indicates leaf level

  public List<TreeViewItem> GetItems(IEnumerable<Entity> source)
  {
    var query =
      from x in source
      group x by KeySelector(x) into g
      let subItems = NextGrouping == null ?
        new List<TreeViewItem>() :
        NextGrouping.GetItems(g)
      select new { Item = ResultSelector(g.Key), SubItems = subItems };

    List<TreeViewItem> result = new List<TreeViewItem>();
    foreach(var queryResult in query)
    {
          // wire up the subitems
      queryResult.Item.SubItems = queryResult.SubItems 
      result.Add(queryResult.Item);
    }
    return result;
  }

}

这样使用:

EntityGrouper companyGrouper = new EntityGrouper()
{
  KeySelector = o => new EntityGroupKey() {ID = o.CompanyID, Name = o.CompanyName},
  ResultSelector = key => new TreeViewItem
  {
    CompanyID = key.ID,
    DisplayName = key.Name,
    ItemTypeEnum = TreeViewItemType.Company
  }
}

EntityGrouper divisionGrouper = new EntityGrouper()
{
  KeySelector = o => new EntityGroupKey() {ID = 0, Name = o.Division},
  ResultSelector = key => new TreeViewItem
  {
    DisplayName = key.Name,
    ItemTypeEnum = TreeViewItemType.Division
  } 
}

companyGrouper.NextGrouping = divisionGrouper;

List<TreeViewItem> oneWay = companyGrouper.GetItems(source);

companyGrouper.NextGrouping = null;
divisionGrouper.NextGrouping = companyGrouper;

List<TreeViewItem> otherWay = divisionGrouper.GetItems(source);

关于c# - 动态创建 GroupBy 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10756571/

相关文章:

c# - WebApi 和 MVC 之间的共享模型

c# - 极端线程安全集合

c# - 如何使用 Linq To XML 获取元素值

c# - 在 azure 上发布时列名无效

C# : LINQ query to list all empty properties of a class

c# - 创建后写入文件时文件正在使用中

c# - Kinect RGB 转 AVI 文件

linq - 如何编写一个 LINQ 查询来反转分层数据源的分组?

c# - nvarchar(max) 和 sql express 2005 的流畅 NHibernate 问题

c# - JSOn 对象未在 wcf web 服务端正确反序列化