简体   繁体   English

将动态匿名对象添加到linq groupBy表达式中

[英]add dynamic anonymous object into linq groupBy expression

I have following linq expression: 我有以下linq表达式:

Func<Entity, object> groupQuery = item => 
     new { a = item.Attributes["name"], item = item.Attributes["number"] };
var result = target.Collection.Entities.GroupBy(groupQuery).ToList();

But if i don't know, how much columns i will group (for example 3 instead of 2),and names of the Attributes stored in List Names, How should i change my groupQuery object? 但是,如果我不知道,我将分组多少列(例如3而不是2),以及存储在列表名称中的属性名称,我应该如何更改我的groupQuery对象? My first idea was to create dynamic object like this but it don't work 我的第一个想法是创建这样的动态对象,但它不起作用

dynamic groupQuery= new ExpandoObject();
IDictionary<string, object> dictionary = (IDictionary<string, object>)groupQuery;

foreach (string str in Names)
{
   dictionary.Add(str, str);
}

Instead of returning an object from groupQuery you can return a string. 您可以返回一个字符串,而不是从groupQuery返回一个对象。 This string will be constructed from properties of objects that you want to group. 此字符串将根据要分组的对象的属性构造。 Depending on the configuration it can be generated in different ways ie based on different properties. 根据配置,它可以以不同的方式生成,即基于不同的属性。 Here is a code that shows an idea: 这是一个显示想法的代码:

public class A
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
}

public enum GroupByuMode
{
    GroupBy1,
    GroupBy2,
    GroupBy3,
}

...

var list = new List<A>();
for (int i = 0; i < 10; ++i)
    for (int j = 0; j < 10; ++j)
        for (int k = 0; k < 10; ++k)
            list.Add(new A { Property1 = i.ToString(), Property2 = j.ToString(), Property3 = k.ToString() });

var mode = GroupByuMode.GroupBy1;

Func<A, object> func = a =>
{
    if (mode == GroupByuMode.GroupBy1)
        return a.Property1;
    else if (mode == GroupByuMode.GroupBy2)
        return String.Format("{0}_{1}", a.Property1, a.Property2);
    else if (mode == GroupByuMode.GroupBy3)
        return String.Format("{0}_{1}_{2}", a.Property1, a.Property2, a.Property3);

    return null;
};

var res = list.GroupBy(func).ToList();
Console.WriteLine(res.Count);

mode = GroupByuMode.GroupBy2;

res = list.GroupBy(func).ToList();
Console.WriteLine(res.Count);

It works witch LINQ to Objects as shown above. 如上所示,它可以使用LINQ to Objects。 You have to check if it works with LINQ to Entities or another implementation of LINQ. 您必须检查它是否适用于LINQ to Entities或LINQ的其他实现。

answer in question C# LINQ - How to build Group By clause dynamically 回答问题C#LINQ - 如何动态构建Group By子句

IEnumerable<string> columnsToGroupBy = new[] { Names.First()};
            Names.RemoveAt(0);
            Names.Aggregate(columnsToGroupBy, (current, query) => current.Concat(new[] {query}));
            GroupQuery = r => new NTuple<object>(from column in columnsToGroupBy select r[column]);
///////
    using System;
    using System.Collections.Generic;
    using System.Linq;

    namespace WBTCB.AggregationService.Models.Helpers
    {
        public class NTuple<T> : IEquatable<NTuple<T>>
        {
            public NTuple(IEnumerable<T> values)
            {
                Values = values.ToArray();
            }

            public readonly T[] Values;

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(this, obj))
                    return true;
                if (obj == null)
                    return false;
                return Equals(obj as NTuple<T>);
            }

            public bool Equals(NTuple<T> other)
            {
                if (ReferenceEquals(this, other))
                    return true;
                if (other == null)
                    return false;
                var length = Values.Length;
                if (length != other.Values.Length)
                    return false;
                for (var i = 0; i < length; ++i)
                    if (!Equals(Values[i], other.Values[i]))
                        return false;
                return true;
            }

            public override int GetHashCode()
            {
                return Values.Aggregate(17, (current, value) => current*37 + (!ReferenceEquals(value, null) ? value.GetHashCode() : 0));
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM