2012-01-10 3 views
4

は、我々は二つのクラスどのように式を作成する:セレクタ+述語ですか?

public class EntityA 
{ 
    public EntityB EntityB { get; set; } 
} 

public class EntityB 
{ 
    public string Name { get; set; } 
    public bool IsDeleted { get; set; } 
} 

とセレクタとpredicatorのための2つの式を持っていると仮定し

Expression<Func<EntityA, EntityB>> selector = c => c.EntityB; 
Expression<Func<EntityB, bool>> predicate = c => c.IsDeleted && c.Name == "AAA"; 

私は私の例では

Expression<Func<TSource, bool>> Compose<TPropType>(Expression<Func<TSource, TPropType>> selector, Expression<Func<TPropType, bool>> predicator) 
{ 
    // Expression API ??? 
} 

のような合成式を返すメソッドを記述する必要があります結果は

です。事前に

Expression<Func<EntityA, bool>> exp = c => c.EntityB.IsDeleted && c.EntityB.Name == "AAA"; 

おかげと同等であるものを10

+0

? – AakashM

+0

はい、あなたは正しいです。修正されました。 – qmicron

答えて

0

あなたは次のことを試すことができます:ここでは

static Expression<Func<TSource, bool>> Compose<TSource, TPropType>(
    Expression<Func<TSource, TPropType>> selector, 
    Expression<Func<TPropType, bool>> predicator) 
{ 
    ParameterExpression param = Expression.Parameter(typeof(TSource), "sourceObj"); 
    Expression invokedSelector = Expression.Invoke(selector, new Expression[] { param }); 
    Expression invokedPredicate = Expression.Invoke(predicator, new[] { invokedSelector }); 

    return Expression.Lambda<Func<TSource, bool>>(invokedPredicate, new[] { param }); 
} 

はそれを使用する方法は次のとおりです。これらのラムダ式を呼び出す

static void Main() 
{ 
    Expression<Func<EntityA, EntityB>> selector = c => c.EntityB; 
    Expression<Func<EntityB, bool>> predicate = c => c.IsDeleted && c.Name == "AAA"; 

    Expression<Func<EntityA, bool>> exp = Compose(selector, predicate); 
    System.Console.WriteLine(exp.Compile()(new EntityA())); 
} 
+0

イゴールありがとうございます、すべて正常に動作します。 – qmicron

2

は確かにあなたがやっているしたくないものです。あなたがしなければならないことは、表現を書き直すことです。ラムダ式を呼び出すかのようにラムダ式に値をバインドする方法が必要です。これを行うには、パラメータを置き換える式の本文を、バインドしている値で書き換えます。あなたはそれを行うために、このSubstitutionVisitorを使用することができます。

public class SubstitutionVisitor : ExpressionVisitor 
{ 
    public Expression OldExpr { get; set; } 
    public Expression NewExpr { get; set; } 

    public override Expression Visit(Expression node) 
    { 
     return (node == OldExpr) ? NewExpr : base.Visit(node); 
    } 
} 

例えばこれらの式を考える:

Expression<Func<EntityA, EntityB>> selector = 
    entityA => entityA.EntityB; 
Expression<Func<EntityB, bool>> predicate = 
    entityB => entityB.IsDeleted && entityB.Name == "AAA"; 

目標は、それはこのようになったので、それを効果的に書き換えることである:

Expression<Func<EntityA, bool>> composed = 
    entity => entity.EntityB.IsDeleted && entity.EntityB.Name == "AAA"; 
static Expression<Func<TSource, bool>> Compose<TSource, TProp>(
    Expression<Func<TSource, TProp>> selector, 
    Expression<Func<TProp, bool>> predicate) 
{ 
    var parameter = Expression.Parameter(typeof(TSource), "entity"); 
    var property = new SubstitutionVisitor 
    { 
     OldExpr = selector.Parameters.Single(), 
     NewExpr = parameter, 
    }.Visit(selector.Body); 
    var body = new SubstitutionVisitor 
    { 
     OldExpr = predicate.Parameters.Single(), 
     NewExpr = property, 
    }.Visit(predicate.Body); 
    return Expression.Lambda<Func<TSource, bool>>(body, parameter); 
} 

ここで何が起こっているのか理解するために、彼は

  1. 作成する新しいラムダの新しいパラメータを作成します。セレクタを考える

    entity => ... 
    
  2. 、特性を得るために、ラムダの身体から私たちの新しいパラメータentityと元のパラメータentityAのすべてのインスタンスを置き換えます。述語を考える

    entityA => entityA.EntityB 
    // becomes 
    entity.EntityB 
    
  3. 、私たちの新しいラムダの体を得るために、ラムダの本体から以前に取得した財産entity.EntityBと元のパラメータentityBのすべてのインスタンスを置き換えます。

    entityB => entityB.IsDeleted && entityB.Name == "AAA" 
    // becomes 
    entity.EntityB.IsDeleted && entity.EntityB.Name == "AAA" 
    
  4. すべてを新しいラムダに入れます。最後の `c.Name == "AAA" が` `c.EntityB.Name == "AAA"`、右でなければなりません

    entity => entity.EntityB.IsDeleted && entity.EntityB.Name == "AAA" 
    
+0

もう一つ解決策はLinqKitを使うことです。この場合 式> output = c => predicate.Invoke(selector.Invoke(c)); – qmicron

+0

私はそう言っていません。それでも、式をコンパイルして呼び出します。ラムダのパラメータへの引数を_bound_していれば、それは解決策だと思います。他の解決策を実行することは本質的により良い方法です。私はそのライブラリにあまり慣れていませんが、私のソリューションの結果を得るためには、式を展開()する必要があるようです。 –

関連する問題