用于 .GroupedBy().Select() 的 Max(DataRow) 的 c# linq MethodCallExpression
c# linq MethodCallExpression for Max(DataRow) used for .GroupedBy().Select()
这里的问题参考我之前的问题
@xanatos 建议的 Sum() 表达式工作得很好。
我也为 double 类型的字段尝试了 Max() 表达式,没有遇到任何问题。
作为下一步,我决定添加 DateTime 字段并为其计算 Max()。
我修改了 GroupSum class 如下:
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();
}
代码编译通过,但在运行时抛出错误。我评论了指令并指定了错误消息。
这很奇怪,因为唯一的区别是
双和(双)
对比
日期时间最大值(日期时间)
无需添加硬编码版本即可。
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;
}
更改此行添加 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);
所以两个泛型类型参数!
这里的问题参考我之前的问题
作为下一步,我决定添加 DateTime 字段并为其计算 Max()。
我修改了 GroupSum class 如下:
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();
}
代码编译通过,但在运行时抛出错误。我评论了指令并指定了错误消息。
这很奇怪,因为唯一的区别是
双和(双)
对比
日期时间最大值(日期时间)
无需添加硬编码版本即可。
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;
}
更改此行添加 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);
所以两个泛型类型参数!