expression.call值不能为null

时间:2015-01-05 19:26:53

标签: vb.net linq expression-trees

我尝试使用表达式树编码此LINQ查询:

Result = Result.Where(Function(Row) Convert.ToInt32(Row(2)) <= 10)

Result被声明为Dim Result As IEnumerable(Of Object())

到目前为止我有这个代码:

Dim queryiabledata As IQueryable(Of Object()) = Result.AsQueryable

Dim pe As ParameterExpression = Expression.Parameter(GetType(String), "Row(2)")
Dim left As expression = Expression.Call(pe, GetType(String).GetMethod("Convert.ToInt32", System.Type.EmptyTypes))
Dim right As Expression = Expression.Constant(10)
Dim e1 As Expression = Expression.LessThanOrEqual(left, right)

Dim predicatebody As Expression = e1
Dim wherecallexpression As MethodCallExpression = Expression.Call(
    GetType(Queryable), "Where", New Type() {queryiabledata.ElementType}, queryiabledata.Expression,
    Expression.Lambda(Of Func(Of Object(), Boolean))(predicatebody, New ParameterExpression() {pe}))

Result = queryiabledata.Provider.CreateQuery(Of Object())(wherecallexpression)

但是如果我运行查询,我会在Expression.Call得到一个ArgumentNullException(Value不能为null。参数名:方法)。

我尝试将"Convert.ToInt32"更改为"Value",但我遇到了同样的错误。

我该如何解决?

另一个代码行是否正确以获得所需的结果?

2 个答案:

答案 0 :(得分:0)

这条线似乎对我很怀疑:

GetType(String).GetMethod("Convert.ToInt32", System.Type.EmptyTypes)

GetType(String)返回运行时类型String。然后,您尝试获取一个名为&#34; Convert.ToInt32&#34;的方法。它不存在于字符串类型中。我怀疑是返回null,这是你的异常的来源。

也许你需要使用这样的东西:

GetType(Convert).GetMethod("ToInt32", new Type() {GetType(Object)})

由于ToInt32类的Convert方法存在多个重载,因此您需要通过提供Type数组作为第二个参数来指定所需的重载。换句话说,你是一个谚语&#34;给我一个带有Object类型的重载作为它的参数&#34;。

答案 1 :(得分:0)

我更习惯于C#,虽然偶尔也会使用VB.NET。 VB.NET中的反思非常难看。获取Where方法有点像黑客攻击。这是代码:

shortFormlongForm应该相同。

    Dim result As IEnumerable(Of Object()) = New List(Of Object())()
    Dim queryiabledata As IQueryable(Of Object()) = result.AsQueryable()
    Dim shortForm As Expression = queryiabledata.Where(Function(Row) Convert.ToInt32(Row(2)) <= 10).Expression

    Dim whereMethod = GetType(Queryable).GetMethods(BindingFlags.Public Or BindingFlags.Static).
        First(Function(m) m.Name = "Where").
        MakeGenericMethod(GetType(Object()))
    Dim convertMethod = GetType(System.Convert).GetMethod("ToInt32", New Type() {GetType(Object)})
    Dim rowParameter = Expression.Parameter(GetType(Object()), "Row")

    Dim longform As Expression =
        Expression.Call(
            whereMethod,
            queryiabledata.Expression,
            Expression.Lambda(
                Expression.LessThanOrEqual(
                    Expression.Call(
                            convertMethod,
                            Expression.ArrayAccess(
                                rowParameter,
                                Expression.Constant(2)
                            )
                        ),
                    Expression.Constant(10)
                ),
                rowParameter
            )
        )
    result = queryiabledata.Provider.CreateQuery(longform)