2009-05-10 7 views
26

...私はそうのようなラムダ式に述語を固執することができるようにExpression <Func <MyClass、bool >>述部を動的に作成するにはどうすればよいですか?私は動的にようになります述語を作成するために、式ツリーを使用しに行くかどう

(p.Length== 5) && (p.SomeOtherProperty == "hello") 

...

q.Where(myDynamicExpression)... 

私はちょうど正しい方向を指す必要があります。

更新:申し訳ありませんが、上記のように述語に複数の条件を設定する必要があるという事実は除外しました。混乱させて申し訳ありません。

答えて

45

オリジナル

ので、同様:

var param = Expression.Parameter(typeof(string), "p"); 
    var len = Expression.PropertyOrField(param, "Length"); 
    var body = Expression.Equal(
     len, Expression.Constant(5)); 

    var lambda = Expression.Lambda<Func<string, bool>>(
     body, param); 

(p.Length== 5) && (p.SomeOtherProperty == "hello")

を更新:

var param = Expression.Parameter(typeof(SomeType), "p"); 
var body = Expression.AndAlso(
     Expression.Equal(
      Expression.PropertyOrField(param, "Length"), 
      Expression.Constant(5) 
     ), 
     Expression.Equal(
      Expression.PropertyOrField(param, "SomeOtherProperty"), 
      Expression.Constant("hello") 
     )); 
var lambda = Expression.Lambda<Func<SomeType, bool>>(body, param); 
+0

感謝を必要としませんが、愚かな私は&&(p.SomeOtherPropertyのような読みする述語...(5 p.Length ==)を希望することを言及するのを忘れてしまいました== "こんにちは")。言い換えれば、どのように条件を連鎖させるのですか? ご迷惑をおかけして申し訳ありません。 – Senkwe

+0

ありがとうございます。私が探していたものに見えます。 ありがとうございました – Senkwe

+0

@マークGravell:私たちが 'SomeType'を持っていなかったら、ラムダをどのように作ることができますか?例:TyepOfEntity = Assembly.GetType(string.Format( "Smartiz.Data。{0} "、EntityName)); ' –

0

式をインスタンス化し、それを式ツリービジュアライザで見ることができます。 Visual Studioのサンプルには1つあります。コンパイルして特定のフォルダに配置することができます。

これは、表現がどのように構成されているかを示す素敵な小さなツリーを提供します。次に、Expressionオブジェクトの静的メソッドでこのような式を構築できます。

9

複数の述語を&&演算子と組み合わせるには、一度に2つずつ結合します。

あなたがpredicatesと呼ばれる表現オブジェクトのリストを持っている場合は、次の操作を行います。

Expression combined = predicates.Aggregate((l, r) => Expression.AndAlso(l, r)); 
1

ラムダ式をお互いに関連付ける: 他の方法は次のコードを使用することです。私のアドバイスでSchotimeの答えよりも柔軟性があり、完璧に動作します。外部ナゲッツは

Frameworkの4.0

// Usage first.Compose(second, Expression.And) 
    public static Expression<T> Compose<T>(this Expression<T> First, Expression<T> Second, Func<Expression, Expression, Expression> Merge) 
    { 
     // build parameter map (from parameters of second to parameters of first) 
     Dictionary<ParameterExpression,ParameterExpression> map = First.Parameters.Select((f, i) => new { f, s = Second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); 

     // replace parameters in the second lambda expression with parameters from the first 
     Expression secondBody = ParameterRebinder.ReplaceParameters(map, Second.Body); 

     // apply composition of lambda expression bodies to parameters from the first expression 
     return Expression.Lambda<T>(Merge(First.Body, secondBody), First.Parameters); 
    } 

    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> First, Expression<Func<T, bool>> Second) 
    { 
     return First.Compose(Second, Expression.And); 
    } 

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> First, Expression<Func<T, bool>> second) 
    { 
     return First.Compose(second, Expression.Or); 
    } 


public class ParameterRebinder : ExpressionVisitor 
{ 
    private readonly Dictionary<ParameterExpression, ParameterExpression> map; 

    public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map) 
    { 
     this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>(); 
    } 

    public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp) 
    { 
     return new ParameterRebinder(map).Visit(exp); 
    } 

    protected override Expression VisitParameter(ParameterExpression p) 
    { 
     ParameterExpression replacement; 
     if (map.TryGetValue(p, out replacement)) 
     { 
      p = replacement; 
     } 
     return base.VisitParameter(p); 
    } 
} 
関連する問題