2009-05-10 10 views
26

... Ben şöyle bir lambda ifadesi içine yüklemi sopa anlamına YaniDinamik olarak bir İfade Oluşturma <Func <MyClass, bool >> predicate? Dinamik şuna benzer bir yüklemi oluşturmak için bir Expression Ağacı kullanma hakkında gitmek nasıl

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

...

q.Where(myDynamicExpression)... 

Sadece doğru yönde işaret edilmem gerek.

Güncelleme: Maalesef, yüklemenin yukarıdaki gibi birden çok koşula sahip olmasını istediğimden vazgeçtim. Karışıklık için özür dilerim.

cevap

45

Orjinal

böylece gibi:

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") yeniden

Güncel:

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

Teşekkür gerekli, ama aptalca ben && (p.SomeOtherProperty gibi okumaya yüklemi ... (5 p.Length ==) istediğinizi belirtmeyi unuttum == "merhaba"). Başka bir deyişle, koşulları nasıl zincirleyebilirim? Temiz olmadığım için üzgünüz – Senkwe

+0

Güncellemeye çok teşekkür ederiz. Aradığım şey gibi görünüyor. Teşekkürler – Senkwe

+0

@Mark Gravell: "SomeType" 'a sahip olmasaydık lambda'yı nasıl oluşturabiliriz. e.g: Biz sadece 'TyepOfEntity = Assembly.GetType (string.Format ("Smartiz.Data) yazın.{0} ", EntityName));' –

0

İfadeyi başlatabilir ve bir İfade Ağacı görselleştiricisiyle inceleyebilirsiniz. Visual studio örneklerinde bir tane var - bunu derleyip daha sonra belirli bir klasöre koyabilirsiniz.

Size, bir ifadenin nasıl oluşturulduğunu gösteren güzel bir küçük ağaç verecektir. Sonra Expression nesnesinin statik yöntemleri ile böyle bir ifade inşa edebilirsiniz.

9

Birkaç yüklemeyi && işleciyle birleştirmek için, bunları her seferinde iki kez birleştirirsiniz.

Eğer predicates denilen İfade nesnelerin bir listesi var Yani eğer bunu:

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

Lambda ifadesini birbiriyle ilişkilendirmek için: Başka bir yol aşağıdaki kodu kullanmaktır. Tavsiyemde Schotime yanıtından daha esnek ve mükemmel çalışıyor. Harici Nuggets

Çerçeve 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); 
    } 
} 
İlgili konular