在动态.NET表达式中使用括号
我有一个网格,用户可以在集合中填写“过滤器”。 用户必须填写一些列:在动态.NET表达式中使用括号,.net,dynamic,linq-expressions,.net,Dynamic,Linq Expressions,我有一个网格,用户可以在集合中填写“过滤器”。 用户必须填写一些列: AndOr Property Comparator Value 比如说,对于城市集合,它可以过滤 - Name StartsWith 'a' AND Population > 10000 OR Population < 1000 在.NET动态表达式库中是否有一些“组”、“打开/关闭括号”? 另一种实现它的方式 在它们之间“链接”行的
AndOr Property Comparator Value
比如说,对于城市集合,它可以过滤
- Name StartsWith 'a'
AND Population > 10000
OR Population < 1000
在.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
处理此问题的最佳方法是在表达式树中使用嵌套的子表达式。这可能涉及改变您解释用户输入的方式。基本上,每当遇到LeftBracket元素时,都会递归地构建一个子表达式,直到当前范围中的下一个rightsbracket元素。然后将整个子表达式指定为当前操作中的节点 通过查看您问题中的代码示例,我怀疑最好在“GetExpressionFromRow”函数中执行此操作。不幸的是,我不认为“GetExpressionFromRow”是您在问题中引用的代码库的一部分 如果您可以将问题更新为包含GetExpressionFromRow和依赖项,我可以尝试进一步检查并给出更具体的答案
这种技术背后的基本算法称为递归下降解析器。请参阅此处的一些一般信息:我认为这是
块
表达式,但不确定。@leppie:不幸的是,我不知道如何在我的情况下使用块表达式…@leppie:块表达式用于将多个表达式组合在一起,以便它们按顺序执行(与代码块类似)。(现在有足够的代表对这个问题进行评论)我可能遗漏了一些东西,但是“嵌套谓词”一节中的内容是什么?你在寻找如何表示包含分组的谓词的指导吗?@AAkashM:我认为海报是在寻找一个更一般化的解释,说明如何动态组合嵌套谓词,以及将其插入现有代码的最佳位置。作为旁注@leppie(由于信誉不足,无法对此问题发表评论),块表达式不是此处的正确答案。块表达式用于将多个表达式组合在一起,以便它们按顺序执行(与代码块类似)
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