【问题标题】:LINQ dynamic method call using expressions使用表达式的 LINQ 动态方法调用
【发布时间】:2011-05-03 18:27:49
【问题描述】:

我正在尝试在扩展 BindingList(Of T) 的类中使用 LINQ 表达式实现多列过滤。以下是相关代码:

Public Function GetFilterPredicate() As Func(Of T, Boolean)
    Dim expressionList As List(Of Expression) = New List(Of Expression)

    For Each item as FilterInfo in _FilterList
        Dim fieldName As String = item.FieldName
        Dim fieldOperator As String = item.FieldOp
        Dim fieldValue As Object = item.FieldValue

        Dim obj As ParameterExpression = Expression.Parameter(GetType(T), "obj")
        Dim objProp As MemberExpression = Expression.PropertyOrField(obj, fieldName)
        Dim filterValue As ConstantExpression = Expression.Constant(fieldValue, objProp.Type)

        Dim methodName As String = If(fieldOperator = "=", "Equal", "NotEqual")

        Dim comparisonExp As MethodCallExpression = Expression.Call( _
            GetType(Expression),
            methodName,
            New Type() {objProp.Type, filterValue.Type},
            objProp, filterValue)

        expressionList.Add(comparisonExp)
    Next

    //
    // combine the expressions in expressionList using Expression.AndAlso
    //
    // create lambda
    //

    Dim fn As Func(Of T, Boolean) = lambda.Compile

    Return fn
End Function

这是打算这样使用的:

Dim source As IQueryable(Of T) = MyBase.Items.ToList.AsQueryable

MyBase.ClearItems()

Dim filterPredicate As Func(Of T, Boolean) = GetFilterPredicate()

For Each item As T In source.Where(filterPredicate)
    MyBase.Items.Add(item)
Next

但是,Expression.Call 语句会引发异常。我不太清楚要提供的正确论据。就像现在一样,我在运行代码时遇到了这个错误:

InvalidOperationException was unhandled:

No generic method 'Equal' on type 'System.Linq.Expressions.Expression' is
compatible with the supplied type arguments and arguments. No type arguments
should be provided if the method is non-generic.

感谢您的帮助。

【问题讨论】:

    标签: .net vb.net linq expression-trees bindinglist


    【解决方案1】:

    与其尝试使用反射来调用“Equal”或“NotEqual”,不如简单地生成一个不同的表达式树。请原谅我糟糕的 VB.NET 语法,但可能是这样的:

        Dim comparisonExp As Expression = 
            If(fieldOperator = "=",
               Expression.Equal(objProp, filterValue), _
               Expression.NotEqual(objProp, filterValue))
    

    【讨论】:

    • 是的,这实际上是我最初使用的,并且有效,但我真的希望更好地理解 Expression.Call 方法。您提供方法名称、参数类型和参数似乎很简单,但我似乎无法让它工作。
    • @ebj4:Expression.Call 方法旨在构建一个实际调用方法的表达式(如.ToString())。由于您正在尝试构建一个进行比较的表达式,因此它根本不适用于此处。
    • @ebj4:不过,如果你想让你的 lambda 返回一个字符串而不是布尔值,你可以这样做Expression.Call(comparisonExp, "ToString",New Type(){})
    • 好的,我想我现在明白了。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多