Динамически вызывайте GroupBy с IEqualityComparer - PullRequest
1 голос
/ 25 сентября 2019

Я хочу создать динамическую реализацию GroupBy, которая игнорирует регистр.Я использую Expression.Call, что позволяет мне передавать выражения в качестве аргументов.

Есть несколько ответов о том, как создать пользовательский компаратор, но этот вопрос о том, как динамически передать компаратор.

Вот полный метод:

public static IQueryable GroupBy(this IQueryable source, string keySelector, string elementSelector, params object[] values)
{
    if (source == null) throw new ArgumentNullException("source");
    if (keySelector == null) throw new ArgumentNullException("keySelector");
    if (elementSelector == null) throw new ArgumentNullException("elementSelector");
    LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, false, values);
    LambdaExpression elementLambda = DynamicExpression.ParseLambda(source.ElementType, null, elementSelector, false, values);

    return source.Provider.CreateQuery(
        Expression.Call(
            typeof(Queryable), 
            "GroupBy", 
            new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
            source.Expression, 
            Expression.Quote(keyLambda), 
            Expression.Quote(elementLambda)
        )
    );
}

Вызов на Queryable.GroupBy создается:

Expression.Call(typeof(Queryable), "GroupBy", 
  new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
  source.Expression, Expression.Quote(keyLambda), Expression.Quote(elementLambda))

Queryable.GroupBy позволяет передать пользовательский IEqualityComparer.Как я могу это сделать?Expression.Call позволяет мне только передавать аргументы типа Expression.

Есть ли другой способ, которым я могу группировать с игнорируемым регистром, например, путем динамического переопределения GetHashCode() ключей?

1 Ответ

0 голосов
/ 26 сентября 2019

Вы должны называть его так же, как обычно, добавляя компаратор в GroupBy call:

return source.Provider.CreateQuery(
    Expression.Call(
        typeof(Queryable),
        "GroupBy", 
        new Type[] { source.ElementType, keyLambda.Body.Type, elementLambda.Body.Type },
        source.Expression,
        Expression.Quote(keyLambda),
        Expression.Quote(elementLambda),
        Expression.Constant(StringComparer.InvariantCultureIgnoreCase)
    )
);
...