【问题标题】:Linq GroupBy - how to specify the grouping key at runtime?Linq GroupBy - 如何在运行时指定分组键?
【发布时间】:2010-05-26 16:00:23
【问题描述】:

有没有一种好方法可以在运行时确定分组键的 Linq GroupBy?例如我希望从用户选择的字段列表中构建分组键 - 你可以这样做吗?我知道如果我将所有内容都转换为字符串表,我可以轻松地做到这一点,但我想知道是否有一种优雅或聪明的方式来完成此任务。

class Item
{
    public int A, B;
    public DateTime D;
    public double X, Y, Z;
}

我有一个名为dataList<Item>。我想做一些事情,比如检索由A 分组的X 的总和,或者由AB 分组的XYZ 的总和。但是应该能够在运行时以某种方式指定哪些字段进入分组。

【问题讨论】:

    标签: c# linq group-by


    【解决方案1】:

    您只需要在运行时构造一个 Func

    var arg = Expression.Parameter(typeof(Item), "item");
    var body = Expression.Property(arg, "D");
    var lambda = Expression.Lambda<Func<Item, DateTime>>(body, arg);
    var keySelector = lambda.Compile();
    

    用法:

    var result = source.GroupBy(keySelector);
    

    如果您在编译时不知道属性的类型,它会稍微(但不是很多)困难。

    【讨论】:

    • 试图这样做,但无法弄清楚语法,感谢您提供的示例。
    • 这对我有帮助 - 谢谢。如果您在编译时不知道 Func 的返回类型,您有什么选择?
    • @NathanRatcliff 你知道这个问题的答案了吗?
    【解决方案2】:

    获取Dynamic LINQ 代码并使用其中的扩展名,允许您使用字符串指定keySelector。

    var query = db.Foo.GroupBy( "{0}", "GroupedProperty", groupKey );
    

    如果您想取回按键分组的整个对象,您可能还需要考虑添加自己的扩展。

    public static IQueryable GroupByComplete( this IQueryable source, string keySelector, params object[] values )
    {
        if (source == null) throw new ArgumentNullException( "source" );
        if (keySelector == null) throw new ArgumentNullException( "keySelector" );
        LambdaExpression keyLambda = DynamicExpression.ParseLambda( source.ElementType, null, keySelector, values );
        return source.Provider.CreateQuery(
            Expression.Call(
                typeof( Queryable ), "GroupBy",
                new Type[] { source.ElementType, keyLambda.Body.Type },
                source.Expression, Expression.Quote( keyLambda ) ) );
    }
    

    【讨论】:

    • 这看起来像我想要的。看源代码,我想它比我想象的要复杂,还好我没有花太多时间自己写:)
    猜你喜欢
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多