c # linq MethodCallExpression для Max (DataRow), используемого для .GroupedBy (). Select () - PullRequest
0 голосов
/ 01 июня 2018

Этот вопрос относится к моему предыдущему вопросу здесь Выражение Sum (), рекомендованное @xanatos, сработало отлично.Я пробовал также выражение Max () для поля типа double и не столкнулось с проблемой.
В качестве следующего шага я решил добавить поле DateTime и рассчитать для него Max ().
Я изменил класс GroupSum следующим образом:

private class GroupSum : GroupKey
{
    public Double AggN0 { get; set; }
    public DateTime AggD0 { get; set; }
}

И запрограммировал функцию:

private static Func<IGrouping<GroupKey, DataRow>, DateTime> GetFuncMaxDateTime()
{
    MethodInfo methInfo = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) });

    ParameterExpression expRow = Expression.Parameter(typeof(DataRow), "row");  //Parametr: (row =>....)

    PropertyInfo propertyInfo = typeof(GroupSum).GetProperty("AggD0");

    MethodCallExpression expCall = GetFieldCallExpression(expRow, methInfo, propertyInfo.PropertyType, "DocumentDate");

    var expRowValues = Expression.Lambda(expCall, expRow);

    ParameterExpression expQuerygroup = Expression.Parameter(typeof(IGrouping<GroupKey, DataRow>), "g");

    //HERE it throws an error: No generic method 'Max' on type 'System.Linq.Enumerable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic. 
    MethodCallExpression expMaxRows = Expression.Call(typeof(Enumerable), "Max", new[] { expRow.Type }, expQuerygroup, expRowValues);

    var max = Expression.Lambda<Func<IGrouping<GroupKey, DataRow>, DateTime>>(expMaxRows, expQuerygroup);
    return max.Compile();
}

Код компилируется, но выдает ошибку во время выполнения.Я прокомментировал инструкцию и указал сообщение об ошибке.Это странно, потому что единственная разница -
double Sum (double)
против
DateTime Max (DateTime)

Нет необходимости добавлять, что жестко закодированная версия работает нормально.

private static IEnumerable<GroupSum> GetListOfGroupedRows(IEnumerable<IGrouping<GroupKey, DataRow>> queryGroup)
{
    IEnumerable<GroupSum> querySelect = queryGroup
        .Select(g => new GroupSum
        {
            KeyS0 = g.Key.KeyS0,
            KeyS1 = g.Key.KeyS1,
            AggN0 = g.Sum(row => row.Field<double>("Amount")),
            AggD0 = g.Max(row => row.Field<DateTime>("DocumentNumber"))
        });
    return querySelect;
}

1 Ответ

0 голосов
/ 01 июня 2018

Измените эту строку, добавив expRowValues.ReturnType:

MethodCallExpression expMaxRows = Expression.Call(
    typeof(Enumerable), 
    nameof(Enumerable.Max), 
    new[] { expRow.Type, expRowValues.ReturnType }, 
    expQuerygroup, 
    expRowValues);

, потому что вы хотите эту перегрузку:

public static TResult Max<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);

так что два параметры универсального типа!

...