构建具有多个字段的 GroupBy 表达式树 [英] Build GroupBy expression tree with multiple fields

查看:14
本文介绍了构建具有多个字段的 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 没有实现 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 表达式树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆