2011-05-03 63 views
1

我想在擴展BindingList(Of T)的類中使用LINQ表達式實現多列過濾。下面是相關代碼:使用表達式的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. 

任何幫助表示讚賞,謝謝。

回答

0

與其嘗試使用反射來調用「Equal」或「NotEqual」,您應該簡單地生成一個不同的表達式樹。請原諒我可憐的VB.NET語法,但這樣的事情也許:

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

呀,這其實就是最初使用我,和它的作品,但我真的希望能更好地瞭解Expression.Call方法。看起來很簡單,你提供的方法名稱,參數類型和參數,但我似乎無法得到它的工作。 – ebj4 2011-05-03 23:13:00

+0

@ ebj4:Expression.Call方法旨在構建一個實際調用方法的表達式(如'.ToString()')。既然你正試圖建立一個比較的表達式,那麼這裏就不適用了。 – StriplingWarrior 2011-05-03 23:18:35

+0

@ ebj4:給你一個想法,雖然,如果你想讓你的lambda返回一個字符串而不是一個布爾值,你可以做'Expression.Call(comparisonExp,「ToString」,New Type(){})' – StriplingWarrior 2011-05-03 23:24:23