动态创建GroupBy语句

Ric*_*per 5 c# linq

我正在尝试动态重新构建一些要在树视图中显示的数据,这将允许用户选择以下三个以下维度来按以下方式对数据进行分组:

Organisation
Company
Site
Division
Department
Run Code Online (Sandbox Code Playgroud)

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

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();
Run Code Online (Sandbox Code Playgroud)

这将给出一个像这样的结构:

+ Company A
  + Site A
    + Division 1
    + Division 2
  + Site B
    + Division 1
+ Company B
  + Site C
    + Division 2
+ Company C
  + Site D
Run Code Online (Sandbox Code Playgroud)

但是,这只能为我提供大量的组合.

我将如何将其转换为可以根据用户选择的三个维度动态创建等效表达式的内容,因此我不必为每个组合创建其中一个表达式!!?

多谢你们.

Amy*_*y B 4

一个有趣的问题。选择一种类型用于分组键,另一种类型用于结果......使得很有可能获得您所要求的结果。

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;
  }

}
Run Code Online (Sandbox Code Playgroud)

这样使用:

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);
Run Code Online (Sandbox Code Playgroud)