1. ホーム
  2. c#

[解決済み] Stringを同等のLINQ Expression Treeに変換する方法は?

2022-04-15 10:54:42

質問

これは、元の問題の簡略版である。

Personというクラスがあります。

public class Person {
  public string Name { get; set; }
  public int Age { get; set; }
  public int Weight { get; set; }
  public DateTime FavouriteDay { get; set; }
}

...そして、インスタンスとしましょう。

var bob = new Person {
  Name = "Bob",
  Age = 30,
  Weight = 213,
  FavouriteDay = '1/1/2000'
}

として、以下のように書きたいと思います。 文字列 をお気に入りのテキストエディターで表示させたいのですが・・・。

(Person.Age > 3 AND Person.Weight > 50) OR Person.Age < 3

この文字列と私のオブジェクト・インスタンスを受け取って、TRUEまたはFALSEを評価したいのです。

以下は、現在の私の考えです。

  1. 基本的な比較演算子と論理演算子をサポートするために、ANTLRに基本的な文法を実装する。Visual Basicのプリケーションと機能セットの一部をここにコピーしようと考えている。 http://msdn.microsoft.com/en-us/library/fw84t893(VS.80).aspx
  2. ANTLRに、与えられた文字列から適切なASTを作成させる。
  3. ASTをウォークして 述語ビルダー フレームワークを使用して、Func<Person, bool>を動的に作成します。
  4. 必要に応じて、Personのインスタンスに対して述語を評価する。

質問ですが、私はこれを完全に焼きすぎてしまったのでしょうか?


EDIT: 選択された解決策

Dynamic Linq Library、特にLINQSamplesで提供されているDynamic Queryクラスを使用することにしました。

以下、コードです。

using System;
using System.Linq.Expressions;
using System.Linq.Dynamic;

namespace ExpressionParser
{
  class Program
  {
    public class Person
    {
      public string Name { get; set; }
      public int Age { get; set; }
      public int Weight { get; set; }
      public DateTime FavouriteDay { get; set; }
    }

    static void Main()
    {
      const string exp = @"(Person.Age > 3 AND Person.Weight > 50) OR Person.Age < 3";
      var p = Expression.Parameter(typeof(Person), "Person");
      var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, exp);
      var bob = new Person
      {
        Name = "Bob",
        Age = 30,
        Weight = 213,
        FavouriteDay = new DateTime(2000,1,1)
      };

      var result = e.Compile().DynamicInvoke(bob);
      Console.WriteLine(result);
      Console.ReadKey();
    }
  }
}

Result は System.Boolean 型であり、この例では TRUE です。

Marc Gravellに感謝します。

含まれるもの システム.Linq.Dynamic nuget パッケージ、ドキュメント こちら

解決方法は?

を使用することはできますか? 動的 linq ライブラリ ということです。特に、私が考えているのは Where 節があります。必要であれば、リスト/配列の中に入れて、ちょうど .Where(string) を追加してください。

var people = new List<Person> { person };
int match = people.Where(filter).Any();

そうでない場合は、パーサーを書くことで ( Expression 私は、クリスマス前の電車通勤中に似たようなものを書きました(ソースは持っていないと思いますが)。