Linq GroupBy - как указать ключ группировки во время выполнения? - PullRequest
3 голосов
/ 26 мая 2010

Есть ли хороший способ сделать Linq GroupBy, где ключ группировки определяется во время выполнения? например Я хочу, чтобы группирующий ключ создавался из выбранного пользователем списка полей. Вы можете это сделать? Я знаю, что могу легко сделать это, если я все перевожу в таблицу строк, но мне было интересно, есть ли изящный или умный способ сделать это иначе.

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

У меня есть List<Item>, называемый data. Я хочу сделать такие вещи, как получить сумму X, сгруппированную по A, или суммы X, Y и Z, сгруппированные по A и B. но какие поля входят в группировку, можно каким-то образом указывать во время выполнения.

Ответы [ 2 ]

8 голосов
/ 26 мая 2010

Все, что вам нужно, это создать 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);

Немного (но не намного) становится сложнее, если вы не знаете тип свойства во время компиляции.

5 голосов
/ 26 мая 2010

Получите код 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 ) ) );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...