我有一个网格,用户可以填写集合上的“过滤器”。 用户必须填写一些列:
AndOr Property Comparator Value
说,对于城市集合,它可以过滤
的城市 - Name StartsWith 'a'
AND Population > 10000
OR Population < 1000
我使用了动态PredicateBuilder,效果非常好,直到出现“括号”要求。
从上面的“查询”中可以看出,在结果集合中,我们将有城市
(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动态表达式库中是否有“Group”,“Open / CloseBracket”? 另一种实现它的方法是什么?
它们之间“链接”行的代码如下
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
答案 0 :(得分:4)
处理此问题的最佳方法是在表达式树中使用嵌套的子表达式。这可能涉及改变您解释用户输入的方式。基本上,只要遇到LeftBracket元素,就会递归地构建一个子表达式,直到当前作用域中的下一个RightBracket元素。然后,您将整个子表达式指定为当前操作中的节点。
通过查看问题中的代码示例,我怀疑最好的位置是“GetExpressionFromRow”函数。不幸的是,我不认为“GetExpressionFromRow”是您在问题中引用的代码库的一部分。
如果您可以更新您的问题以包含GetExpressionFromRow和依赖项,我可以尝试进一步检查并提供更具体的答案。
这种技术背后的基本算法称为递归下降解析器。请在此处查看一些常规信息:http://en.wikipedia.org/wiki/Recursive_descent_parser