I have this query:
Dim test = result.GroupBy(Function(row) groupedindexes.Select(
Function(grpindex) row(grpindex)).ToArray, comp).
Select(Function(g) New groupedresult(g.Key, g.Sum(Function(x) Convert.ToInt32(x(3)))))
At the moment, I'm building this: g.Sum(Function(x) Convert.ToInt32(x(3)))
I have this so far:
Dim groupparameter = Expression.Parameter(GetType(Linq.IGrouping(Of Object(), Object())), "g")
Dim objectparameter = Expression.Parameter(GetType(Object()), "x")
convertMethod = GetType(System.Convert).GetMethod("ToInt32", New Type() {GetType(Object)})
Dim aggregator_expr As LambdaExpression = Expression.Lambda(expression.Call(convertMethod, Expression.ArrayAccess(objectparameter, Expression.Constant(3))), objectparameter)
Dim aggregator_func = GetType(Enumerable).GetMethods(BindingFlags.Public Or BindingFlags.Static).
Where(Function(m) m.Name = "Sum").Where(Function(m) m.ReturnType.FullName = "System.Int32").First
Dim aggregation As Expression = Expression.Call(aggregator_func, groupparameter, aggregator_expr)
At the last row, vs says:
Incorrect number of arguments supplied for call to method 'Int32 Sum(System.Collections.Generic.IEnumerable`1[System.Int32])'
Sure, there is one parameter more. But if I remove the groupparameter, I get another error message. How can I correct this?
Thanks.
EDIT:
here a simple console application:
Imports System.Reflection
Imports System.Linq.Expressions
Module Module1
Dim groupparameter = Expression.Parameter(GetType(Linq.IGrouping(Of Object(), Object())), "g")
Dim objectparameter = Expression.Parameter(GetType(Object()), "x")
Dim convertMethod = GetType(System.Convert).GetMethod("ToInt32", New Type() {GetType(Object)})
Dim aggregator_expr As LambdaExpression = Expression.Lambda(
Expression.Call(convertMethod, Expression.ArrayAccess(objectparameter, Expression.Constant(3))), objectparameter)
Dim aggregator_func = GetType(Enumerable).GetMethods(BindingFlags.Public Or BindingFlags.Static).
Where(Function(m) m.Name = "Sum").Where(Function(m) m.ReturnType.FullName = "System.Int32" AndAlso m.GetParameters.Length = 2)(0).
MakeGenericMethod(GetType(System.Func(Of Object(), Integer)))
Sub Main()
Dim aggregation As Expression = Expression.Call(Nothing, aggregator_func, aggregator_expr, groupparameter)
End Sub
End Module
As you see, I changed a bit the aggregator_func
. I would like to call this expression: g.Sum(Function(x) Convert.ToInt32(x(3)))
.
I have all together, I need only to call the variables in the right order. But I don't get it.
EDIT: The code can simply copy&paste in vs to see, what is wrong.
Firstly, you're looking in Enumerable
for methods - that's not a good idea if you're trying to work with expression trees. You should be looking in Queryable
.
Next, you need to understand that the Sum
method is overloaded - and there are multiple methods which return Int32
. You need to check whether the method has two parameters. Note that you can check for multiple conditions in a single Where
. For example:
Where(Function(m) m.Name = "Sum" AndAlso
m.ReturnType = GetType(Integer) AndAlso
m.GetParameters().Length = 2)
Hopefully that should at least find you the right method to call. I can't easily tell whether that's all that's wrong (a short but complete program demonstrating what you're trying to do would help) but it should at least get you closer.
EDIT: The parameters you're using are all over the place. For example, you've got an IGrouping<object[], object[]>
- that isn't an IEnumerable<Func<object[], int>>
- it's an IEnumerable<object[]>
. And you're currently specifying the arguments in the wrong order too - the target of an extension method is the first parameter. So here's a short but complete program that doesn't throw an exception:
Imports System.Reflection
Imports System.Linq.Expressions
Class Test
Shared Sub Main()
Dim groupParameter = Expression.Parameter(GetType(Linq.IGrouping(Of Object(), Object())), "g")
Dim objectParameter = Expression.Parameter(GetType(Object()), "x")
Dim convertMethod = GetType(System.Convert).GetMethod("ToInt32", New Type() {GetType(Object)})
Dim aggregatorExpr As LambdaExpression = Expression.Lambda(
Expression.Call(
convertMethod,
Expression.ArrayAccess(objectParameter, Expression.Constant(3))
), objectParameter)
Dim aggregatorFunc = GetType(Enumerable) _
.GetMethods(BindingFlags.Public Or BindingFlags.Static) _
.Where(Function(m) m.Name = "Sum") _
.Where(Function(m) m.ReturnType.FullName = "System.Int32") _
.Where(Function(m) m.GetParameters.Length = 2)(0) _
.MakeGenericMethod(GetType(Object()))
Dim aggregation As Expression = Expression.Call(
Nothing,
aggregatorFunc,
groupParameter,
aggregatorExpr)
End Sub
End Class
See more on this question at Stackoverflow