2

我有一个网格,用户可以在集合上填写“过滤器”。用户必须填写一些列:

AndOr  Property  Comparator  Value

比如说,对于一个 Cities 集合,它可以过滤那些

   -  Name       StartsWith  'a'
  AND Population     >       10000
  OR  Population     <       1000

我使用了动态PredicateBuilder,效果很好,直到出现“括号”要求。

正如您从上面的“查询”中看到的那样,在结果集合中,我们将有城市 which
(Name.StartsWith'a' AND Population > 10000) OR (Population < 1000)

为了构建表达式
Name.StartsWith'a' AND (Population > 10000 OR (Population < 1000) ,我需要使用一些括号。

现在,过滤器网格列更改为

AndOr  LeftBracket  Property  Comparator  Value  RightBracket

.NET 动态表达式库中是否有一些“组”、“打开/关闭括号”?另一种实现方式?

在它们之间“链接”行的代码如下

Private Function GetMyObjectsDataSource() As IQueryable(Of MyObject)
  ' start without any filter, get it all '
  Dim predicate = PredicateBuilder.True(Of MyObject)()
  Dim filterExpression As Expression(Of Func(Of MyObject, Boolean)) = predicate

  For Each row In grdFilter.Rows
    Dim rowExpression = GetExpressionFromRow(Of MyObject)(row)
    Dim compOp As LogicalOperator = row.Cells(ColumnKeys.AndOr).Value

    If compOp = LogicalOperator.Or Then
      filterExpression = [Or](filterExpression, rowExpression)
    Else
      filterExpression = [And](filterExpression, rowExpression)
    End If
  Next row

  Dim myObjects As List(Of MyObject) = Me._Container.GetMyObjects()
  Dim result As IQueryable(Of MyObject) =
    myObjects.AsQueryable().Where(filterExpression)

  Return result
End Function
4

1 回答 1

4

处理这个问题的最好方法是在表达式树中使用嵌套的子表达式。这可能涉及更改您解释用户输入的方式。基本上,每当您遇到 LeftBracket 元素时,您都会递归地构建一个子表达式,直到当前范围内的下一个 RightBracket 元素。然后,您会将整个子表达式分配为当前操作中的一个节点。

通过查看您问题中的代码示例,我怀疑执行此操作的最佳位置是在“GetExpressionFromRow”函数中。不幸的是,我认为“GetExpressionFromRow”不是您在问题中引用的代码库的一部分。

如果您可以更新您的问题以包含 GetExpressionFromRow 和依赖项,我可以尝试进一步检查并给出更具体的答案。

这种技术背后的基本算法称为递归下降解析器。在此处查看一些一般信息:http ://en.wikipedia.org/wiki/Recursive_descent_parser

于 2011-09-08T19:03:03.467 回答