开发者

Using brackets in dynamic .NET expressions

开发者 https://www.devze.com 2023-04-03 04:48 出处:网络
I have a grid in witch 开发者_开发技巧a user can fill-in the \"filter\" on a collection. The user has to fill-in some columns:

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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号