我试图创建一个通用函数来从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