c# linq MethodCallExpression for Max(DataRow) used for .GroupedBy().Select()

早过忘川 提交于 2019-12-11 08:54:46

问题


The question hereby refers to my previous question here The Sum() expression advised by @xanatos worked perfectly. I tried also Max() expression for the field of the type double and faced no issue.
As the next step I decided to add the DateTime field and calculate Max() for it.
I modified the GroupSum class as follows:

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

And programmed the function:

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

The code compiles but it throws an error at runtime. I commented the instruction and specified the error message. It is strange because the only difference is
double Sum(double)
vs
DateTime Max(DateTime)

No need to add that hardcoded version works ok.

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:


Change this line adding expRowValues.ReturnType:

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

because you want this overload:

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

so two generic type parameters!



来源:https://stackoverflow.com/questions/50639052/c-sharp-linq-methodcallexpression-for-maxdatarow-used-for-groupedby-select

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!