2011-05-18 76 views
2

我試圖創建一個通用函數來從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 

非常感謝您提供任何幫助,您可能會提供。

+0

這裏有一個[鏈接](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

+0

正如承諾的,[這裏](http://snipt.org/xLkp)是我最終解決方案的鏈接。事實證明,這是一個巨大的痛苦,因爲你不能使用Type變量作爲ctype中的參數或vb中的DirectCast,並且你不能對同一類型的對象和可空對象進行linq比較。如果有人有一個更好的算法隨時發佈。 – dtryan 2011-05-23 16:56:13

回答

3

爲什麼是And謂詞的原因會創建一個新的表達式,您不保存。它不修改現有的。你需要每returnPred.And線切換到

returnPred = returnPred.And(... 
+0

你是對的 - 我還是Linq的新手。在應用修復程序後,我收到錯誤消息,「LINQ to Entities不支持LINQ表達式節點類型'Invoke'。」你知道有什麼辦法嗎? – dtryan 2011-05-18 16:31:45

+1

@dtryan我不太瞭解LINQ to Entities知道答案。我相信雖然這是因爲沒有辦法將它轉換爲實體呼叫。如果你問另一個Q,但肯定會有一個LINQ to Entity用戶知道答案;) – JaredPar 2011-05-18 16:33:15

相關問題