2

ユーザーがコレクションの「フィルター」に入力できるグリッドがあります。ユーザーはいくつかの列に入力する必要があります。

AndOr  Property  Comparator  Value

たとえば、Citiesコレクションの場合、次の都市をフィルタリングできます。

   -  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動的式ライブラリに「グループ」、「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
4

1 に答える 1

4

これに対処する最善の方法は、式ツリーでネストされたサブ式を使用することです。これには、ユーザーの入力を解釈する方法を変更することが含まれる可能性があります。基本的に、LeftBracket 要素に遭遇するたびに、現在のスコープ内の次の RightBracket 要素までサブ式を再帰的に作成します。次に、その部分式全体を現在の操作のノードとして割り当てます。

あなたの質問のコード サンプルを確認すると、これを行うのに最適な場所は "GetExpressionFromRow" 関数であると思われます。残念ながら、「GetExpressionFromRow」は、質問で参照したコード ライブラリの一部ではないと思います。

GetExpressionFromRow と依存関係を含めるように質問を更新できる場合は、さらに調査して、より具体的な回答を提供することができます。

この手法の背後にある基本的なアルゴリズムは、再帰降下パーサーと呼ばれます。ここでいくつかの一般的な情報を参照してください: http://en.wikipedia.org/wiki/Recursive_descent_parser

于 2011-09-08T19:03:03.467 に答える