用多个字段构建GroupBy表达式树

用多个字段构建GroupBy表达式树

本文介绍了用多个字段构建GroupBy表达式树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要动态生成GroupBy表达式,我试图构建一个Linq表达式树.要分组的字段是动态的,并且可以在数量上有所不同.

To dynamically generate a GroupBy expression, I am trying to build a Linq expression tree. The fields to group by are dynamic and can differ in number.

我使用以下代码:

string[] fields = {"Name", "Test_Result"};
Type studentType = typeof(Student);

var itemParam = Expression.Parameter(studentType, "x");

var addMethod = typeof(Dictionary<string, object>).GetMethod(
    "Add", new[] { typeof(string), typeof(object) });
var selector = Expression.ListInit(
        Expression.New(typeof(Dictionary<string,object>)),
        fields.Select(field => Expression.ElementInit(addMethod,
            Expression.Constant(field),
            Expression.Convert(
                Expression.PropertyOrField(itemParam, field),
                typeof(object)
            )
        )));
var lambda = Expression.Lambda<Func<Student, Dictionary<string,object>>>(
    selector, itemParam);

该代码是从这篇文章(感谢Mark Gravel!)复制的.

The code is copied from this post (Thanks Mark Gravel!).

它最终以...

var currentItemFields = students.Select(lambda.Compile());

...我希望我可以将其更改为...

... of which I expected that I could change it to ...

var currentItemFields = students.GroupBy(lambda.Compile());

我认为lambda表达式只不过是...

I assumed that the lambda expression is nothing more than ...

var currentItemFields = students.GroupBy(o => new { o.Name, o.Test_Result });

...但是不幸的是事实并非如此.具有动态lambda的GroupBy不会给出任何异常,它只是不对任何内容进行分组并返回所有元素.

... but unfortunally that seems not to be the case. The GroupBy with a dynamic lambda does not give any exceptions, it just doesn't group anything and returns all elements.

我在这里做错了什么?任何帮助,将不胜感激.预先感谢.

What am I doing wrong here? Any help would be appreciated. Thanks in advance.

推荐答案

该lambda表达式构建了一个分组字段字典.
Dictionary<TKey, TValue>不实现Equals()GetHashCode(),因此它通过引用相等对它们进行分组.
由于您总是返回新的字典,因此每个项目都有其自己的组.

That lambda expression builds a dictionary of grouping fields.
Dictionary<TKey, TValue> does not implement Equals() and GetHashCode(), so it groups them by reference equality.
Since you always return a new dictionary, each item gets its own group.

您需要对其进行更改以创建正确实现Equals()GetHashCode()以实现值相等的类型.
通常,您将让编译器生成一个匿名类型.但是,由于您在编译时不知道类型签名,因此您不能在此处执行此操作.
相反,您可以构造一个Tuple<...>:

You need to change it to create a type that correctly implements Equals() and GetHashCode() for value equality.
Ordinarily, you would have the compiler generate an anonymous type. However, you can't do that here since you don't know the type signature at compile-time.
Instead, you can construct a Tuple<...>:

Expression.New(
    Type.GetType("System.Tuple`" + fields.Length)
        .MakeGenericType(fields.Select(studentType.GetProperty),
    fields.Select(f => Expression.PropertyOrField(itemParam, f))
)

这篇关于用多个字段构建GroupBy表达式树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 19:59