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.
任何幫助表示讚賞,謝謝。
呀,這其實就是最初使用我,和它的作品,但我真的希望能更好地瞭解Expression.Call方法。看起來很簡單,你提供的方法名稱,參數類型和參數,但我似乎無法得到它的工作。 – ebj4 2011-05-03 23:13:00
@ ebj4:Expression.Call方法旨在構建一個實際調用方法的表達式(如'.ToString()')。既然你正試圖建立一個比較的表達式,那麼這裏就不適用了。 – StriplingWarrior 2011-05-03 23:18:35
@ ebj4:給你一個想法,雖然,如果你想讓你的lambda返回一個字符串而不是一個布爾值,你可以做'Expression.Call(comparisonExp,「ToString」,New Type(){})' – StriplingWarrior 2011-05-03 23:24:23