2

私は単純なルールエンジンhttp://netmatze.wordpress.com/2012/01/22/building-a-rule-engine-in-c/を見ていましたが、これと非常によく似たことをしています。次のような2つのクラスがあります。

    class A
    {
      public List<B> ListB { get; set; }
    }

    Class B
    {
      public int ID { get; set; }
    }

私のルールセットは次のようになります:

    List<Rule> rules = new List<Rule>{
      new Rule("listB", ExpressionType.Loop, 1, "ID")
    };

クラス A のプロパティ listB を基本的に調べる式を作成しようとしています。各項目の ID プロパティをループして、少なくとも 1 つが 1 に等しいかどうかを確認します。これを行う方法に問題があります。私は現在、次のようなものを持っています(これにはハードコードされた値が設定されていますが、最終的には可能な限り一般的になるように変更されます)。この式は機能しません。コンパイル例外が発生します。

    var parameterExpression = Expression.Parameter(typeof(A));
    var listB = MemberExpression.Property(parameterExpression, "ListB");
    var leftOperand = MemberExpression.Property(Expression.Parameter(typeof(B)), "ID");
    var rightOperand = Expression.Constant(1); //1
    var found = Expression.Variable(typeof(bool), "found");

    return Expression.Lambda<Func<T, bool>>(
          Expression.Block(
              listB,
              found,
              Expression.Loop( 
                Expression.Block(
                  Expression.IfThen(
                    Expression.Equal(
                      leftOperand,
                      rightOperand
                     ),//equal
                     Expression.Assign(
                       found,
                       Expression.Constant(true)
                     )//set to true
                  )                     
                )//block
              )//loop
            ),
            A
      ).Compile();

次のように、オブジェクトに対してルール セットを呼び出すことになります。

    Engine ruleEngine = new Engine();
    var compiledRules = rules.Select(r => ruleEngine.CompileRule<A>(r)).ToList();
    var result = compiledRules.All(rule => rule(objA));

私の質問は次のとおりです。

  1. リスト項目のいずれかが条件に一致した場合に、この関数が true/false を返すようにするにはどうすればよいですか。
  2. すべてのリスト項目が比較された後 (そしてどれも一致しなかった場合)、Expression.Loop がループを停止するのを防ぐにはどうすればよいですか?

助けてくれてありがとう。

4

2 に答える 2

1

ループを使用する理由 C# でチェックをコーディングしている場合は、ループを使用しません。を使用しますEnumerable.Any。したがって、次の式を生成します。

A a;
return a.ListB.Any(b => b.ID == 1);

これは次のように翻訳されます。

A a;
return Enumerable.Any(a.ListB, b => b.ID == 1);

これは式ツリーに簡単に変換できます。

于 2014-03-27T17:37:49.860 に答える
0

最後のコメントに続いて、私が別の質問に提案したアプローチを使用できるようです。この部品を交換します:

var childProperty = parameter.Type.GetProperty(properties[0]);
var left = Expression.Property(parameter, childProperty);
var right = Expression.Constant(test, typeof(int));
navigationPropertyPredicate = Expression.Equal(left, right);
resultExpression = MakeLambda(parameter, navigationPropertyPredicate);

あなたのruleOperatorと値を使用して何か

于 2014-03-28T07:24:27.023 に答える