2011-05-18 49 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

相关问题