我試圖創建一個通用函數來從Telerik網格過濾器列表構建一個Linq表達式。我正在努力避開動態的Linq。因爲我不知道構建表達式的類型,所以我試圖在lambda函數中使用反射來引用屬性,但是我的結果從不被過濾。調用我的幫助器函數來獲取屬性值從來不會被調用,儘管它確實擊中了「添加」行。將反思放在一條線上(如下面的「GreaterThan」)並沒有什麼不同。這裏是我的代碼:lambda函數中的未知類型的引用屬性
Public Shared Function buildRadFilter(Of T)(ByVal filterExpression As List(Of GridFilterExpression)) As Expressions.Expression(Of Func(Of T, Boolean))
Dim returnPred = PredicateBuilder.True(Of T)()
For Each exp As GridFilterExpression In filterExpression
Dim iExp = exp
Dim doDefault = False
Select Case iExp.FilterFunction
Case "Contains"
returnPred.And(Function(x) DirectCast(propVal(x, iExp.FieldName), String).Contains(iExp.FieldValue))
Case "DoesNotContain"
returnPred.And(Function(x) Not DirectCast(propVal(x, iExp.FieldName), String).Contains(iExp.FieldValue))
Case "StartsWith"
returnPred.And(Function(x) DirectCast(propVal(x, iExp.FieldName), String).StartsWith(iExp.FieldValue))
Case "EndsWith"
returnPred.And(Function(x) DirectCast(propVal(x, iExp.FieldName), String).EndsWith(iExp.FieldValue))
Case "EqualTo"
returnPred.And(Function(x) propVal(x, iExp.FieldName) = iExp.FieldValue)
Case "NotEqualTo"
returnPred.And(Function(x) propVal(x, iExp.FieldName) <> iExp.FieldValue)
Case "GreaterThan"
'returnPred.And(Function(x) propVal(x, iExp.FieldName) > iExp.FieldValue)
returnPred.And(Function(x) x.GetType().GetProperty(iExp.FieldName).GetValue(x, Nothing))
Case "GreaterThanOrEqualTo"
returnPred.And(Function(x) propVal(x, iExp.FieldName) >= iExp.FieldValue)
Case "LessThan"
returnPred.And(Function(x) propVal(x, iExp.FieldName) < iExp.FieldValue)
Case "LessThanOrEqualTo"
returnPred.And(Function(x) propVal(x, iExp.FieldName) <= iExp.FieldValue)
Case "IsEmpty"
returnPred.And(Function(x) propVal(x, iExp.FieldName) = "")
Case "NotIsEmpty"
returnPred.And(Function(x) propVal(x, iExp.FieldName) <> "")
Case "IsNull"
returnPred.And(Function(x) propVal(x, iExp.FieldName) Is Nothing)
Case "NotIsNull"
returnPred.And(Function(x) propVal(x, iExp.FieldName) IsNot Nothing)
Case "Between"
Dim vals As String() = iExp.FieldValue.Split(" ")
If vals.Length > 1 Then
returnPred.And(Function(x) propVal(x, iExp.FieldName) >= vals(0) AndAlso propVal(x, iExp.FieldName) <= vals(1))
Else
doDefault = True
Exit Select
End If
Case "NotBetween"
Dim vals As String() = iExp.FieldValue.Split(" ")
If vals.Length > 1 Then
returnPred.And(Function(x) propVal(x, iExp.FieldName) < vals(0) OrElse propVal(x, iExp.FieldName) > vals(1))
Else
doDefault = True
Exit Select
End If
Case Else
doDefault = True
Exit Select
End Select
If doDefault Then
returnPred.And(Function(x) DirectCast(propVal(x, iExp.FieldName), String).StartsWith(iExp.FieldValue))
End If
Next
Return returnPred
End Function
'only works for scalar values
Public Shared Function propVal(ByRef obj As Object, ByVal name As String) As Object
Return obj.GetType().GetProperty(name).GetValue(obj, Nothing)
End Function
非常感謝您提供任何幫助,您可能會提供。
這裏有一個[鏈接](http://stackoverflow.com/questions/10524/expression-invoke-in-entity-framework)修復「的LINQ表達式節點類型「調用」在LINQ to Entities中不受支持。「錯誤。請注意,它只是'.AsExpandable'而不是'.AsExpandable()'(至少對於vb.net)。一旦我有最終解決方案,我會再次發佈它,因爲我沒有在任何地方找到類似的東西。 – dtryan 2011-05-18 16:51:18
正如承諾的,[這裏](http://snipt.org/xLkp)是我最終解決方案的鏈接。事實證明,這是一個巨大的痛苦,因爲你不能使用Type變量作爲ctype中的參數或vb中的DirectCast,並且你不能對同一類型的對象和可空對象進行linq比較。如果有人有一個更好的算法隨時發佈。 – dtryan 2011-05-23 16:56:13