Использование скобок в динамических выражениях .NET - PullRequest
2 голосов
/ 05 сентября 2011

У меня есть сетка, в которой пользователь может заполнить «фильтр» в коллекции.Пользователь должен заполнить несколько столбцов:

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

Есть ли какая-то группа?"," Open / CloseBracket "в библиотеке динамических выражений .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

1 Ответ

4 голосов
/ 08 сентября 2011

Лучший способ справиться с этим - использовать вложенные подвыражения в вашем дереве выражений.Это, вероятно, включает в себя изменение способа интерпретации ввода пользователя.По сути, всякий раз, когда вы сталкиваетесь с элементом LeftBracket, вы рекурсивно создаете подвыражение до следующего элемента RightBracket в текущей области видимости.Затем вы могли бы назначить все это подвыражение как узел в текущей операции.

Из рассмотрения примера кода в вашем вопросе я подозреваю, что лучшее место для этого - функция GetExpressionFromRow.К сожалению, я не думаю, что «GetExpressionFromRow» является частью библиотеки кода, на которую вы ссылались в своем вопросе.

Если вы можете обновить свой вопрос, включив в него GetExpressionFromRow и зависимости, я могу попытаться изучить дальше и датьболее конкретный ответ.

Основной алгоритм, лежащий в основе этой техники, называется анализатором рекурсивного спуска.Смотрите общую информацию здесь: http://en.wikipedia.org/wiki/Recursive_descent_parser

...