I have a grid in witch 开发者_开发技巧a user can fill-in the "filter" on a collection. The user has to fill-in some columns:
AndOr Property Comparator Value
say, for a Cities collection it could filter cities that
- Name StartsWith 'a'
AND Population > 10000
OR Population < 1000
I used the dynamic PredicateBuilder, that worked very well, until the "brackets" requirement appeared.
As you can see from the "query" above, in the resulting collection we will have cities which
(Name.StartsWith'a' AND Population > 10000) OR (Population < 1000)
.
In order to build the expression
Name.StartsWith'a' AND (Population > 10000 OR (Population < 1000)
I need to use some brackets.
Now, the filter grid columns changed to
AndOr LeftBracket Property Comparator Value RightBracket
Is there some "Group", "Open/CloseBracket" in the .NET Dynamic Expression library? An other way to realize it?
The code to "link" rows between them was the following
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
The best way to deal with this is to use nested sub-expressions in your expression tree. This likely involves changing the way you are interpreting the user's input. Basically whenever you encounter a LeftBracket element, you would recursively build a sub-expression up to the next RightBracket element in the current scope. Then you would assign that entire sub-expression as a node in the current operation.
From reviewing the code sample in your question, I would suspect the best place to do this is in the "GetExpressionFromRow" function. Unfortunately, I don't think the "GetExpressionFromRow" is part of the code library you referenced in your question.
If you can update your question to include the GetExpressionFromRow and dependencies, I can try to examine further and give a more specific answer.
The basic algorithm behind this technique is called a recursive descent parser. See some general information here: http://en.wikipedia.org/wiki/Recursive_descent_parser
精彩评论