LINQ:动态谓词生成器问题

LINQ:动态谓词生成器问题,linq,entity-framework,dynamic,predicate,predicatebuilder,Linq,Entity Framework,Dynamic,Predicate,Predicatebuilder,我试图创建一个帮助器类来轻松构建动态LINQ查询。代码是这篇优秀的CodeProject文章的经过大量修改的版本:该文章在此处使用了PredicateBuilder: 我仍在清理代码,所以变量名称目前是垃圾,而且看不到任何注释 用法 实体 用于搜索的存储: 方法 还有有问题的方法 有什么问题 最后一种方法中由五个星号包围的行就是问题所在 将或分组表达式添加到原始谓词生成器时 参数“f”未在指定的LINQ中绑定到实体 查询表达式 由于某些原因,我似乎无法创建嵌套表达式。 如果您将代码放在usage

我试图创建一个帮助器类来轻松构建动态LINQ查询。代码是这篇优秀的CodeProject文章的经过大量修改的版本:该文章在此处使用了PredicateBuilder:

我仍在清理代码,所以变量名称目前是垃圾,而且看不到任何注释

用法

实体

用于搜索的存储:

方法

还有有问题的方法

有什么问题

最后一种方法中由五个星号包围的行就是问题所在

将或分组表达式添加到原始谓词生成器时

参数“f”未在指定的LINQ中绑定到实体 查询表达式

由于某些原因,我似乎无法创建嵌套表达式。 如果您将代码放在usage sample中执行查询的位置之上,则在生成一些mod之后,它就会工作

使用解决方案更新:

带星号的行需要更改为
Return predicate.Andinner.Expand

我不是Visual Basic人员,但在C实现中,我认为您可能需要根据albahari.com/nutshell/predicatebuilder.aspx向查询添加可扩展项。

谢谢Aaron的提示。想做一个回答,这样我就可以接受吗?完成了-很高兴我能帮上忙。顺便问一下,VisualBasic实现是什么样子的?为了子孙后代的利益,您可以编辑您的问题,将其包括在内:D
    Dim conditions As New List(Of Condition)
    With conditions
        .Add(New Condition With {.Field = "EatsPeople", .Operator = "Equals", .Value = False})
        .Add(New Condition With {.Field = "Name", .Operator = "Equals", .Value = "Adric"})
        .Add(New Condition With {.Field = "Description", .Operator = "Contains", .Value = "ugly"})
    End With

    Dim predicate = BuildPredicate(conditions)
    Dim tester = data.Monsters.AsExpandable.Where(predicate).ToList
Public Class Monster
    Public Property EatsPeople As Boolean
    Public Property Name As String
    Public Property Description As String
End Class
Public Class Condition
    Public Property Field As String
    Public Property [Operator] As String
    Public Property Value As Object
End Class
Public Function BuildPredicate(conditions As List(Of Condition)) As Expression(Of Func(Of Monster, Boolean))

    Dim predicate = PredicateBuilder.True(Of Monster)()
    For Each c In conditions
        Dim dbFieldName = c.Field
        Dim dbType = GetType(Monster)
        Dim dbFieldMemberInfo = dbType.GetMember(dbFieldName, BindingFlags.IgnoreCase Or BindingFlags.Public Or BindingFlags.Instance).Single()

        predicate = BuildExpression(c, dbType, dbFieldMemberInfo, predicate)
    Next
    Return predicate

End Function

Private Function CreateLambda(value As Object, method As MethodInfo, ByVal dbType As Type, ByVal dbFieldMemberInfo As MemberInfo) As Expression(Of Func(Of Monster, Boolean))

    Dim dbTypeParameter = Expression.Parameter(dbType, "x")
    Dim dbFieldMember = Expression.MakeMemberAccess(dbTypeParameter, dbFieldMemberInfo)
    Dim criterionConstant = New Expression() {Expression.Constant(value)}
    Dim containsCall = Expression.Call(dbFieldMember, method, criterionConstant)
    Return TryCast(Expression.Lambda(containsCall, dbTypeParameter), Expression(Of Func(Of Monster, Boolean)))

End Function
Private Function BuildExpression(condition As Condition, ByVal dbType As Type, ByVal dbFieldMemberInfo As MemberInfo, ByVal predicate As Expression(Of Func(Of Monster, Boolean))) As Expression(Of Func(Of Monster, Boolean))

    Dim type = condition.Value.GetType
    Dim method As MethodInfo = type.GetMethod(condition.Operator, BindingFlags.Instance Or BindingFlags.Public, Nothing, {type}, Nothing)

    If type = GetType(String) Then

        If condition.Value.ToString.Contains(",") = True Then

            Dim inner = PredicateBuilder.False(Of Product)()
            For Each v In condition.Value.ToString.Split(",")
                inner = inner.Or(CreateLambda(v, method, dbType, dbFieldMemberInfo))
            Next     
            *****Return predicate.And(inner)*****
        End If

    End If

    Return predicate.And(CreateLambda(condition.Value, method, dbType, dbFieldMemberInfo))

End Function