Linq GroupBy - 如何在运行时指定分组键?

时间:2010-05-26 16:00:23

标签: c# linq group-by

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

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

我有List<Item>名为data。我想要检索XA分组的总和,或XYZ的总和,按{{ 1}}和A。但是进入分组的哪些字段应该能够在运行时以某种方式指定。

2 个答案:

答案 0 :(得分:8)

你需要的只是构造一个Func&lt; Item,TKey&gt;在运行时:

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

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

答案 1 :(得分:5)

获取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 ) ) );
}