2011-03-25 14 views
11

मैं विशिष्टता ऑब्जेक्ट के आधार पर गतिशील रूप से अभिव्यक्तियों का निर्माण करने की कोशिश कर रहा हूं।एक अभिव्यक्ति के शरीर में पैरामीटर नाम को बदलना

private Expression<Func<T, bool>> expression; 

public ExpressionHelper() 
{ 
    expression = (Expression<Func<T, bool>>)(a => true); 
} 

और फिर कुछ आसान तरीके इस प्रकार:

मैं एक ExpressionHelper वर्ग है कि इतने की तरह एक निजी अभिव्यक्ति बना लिया है

public void And(Expression<Func<T,bool>> exp); 

मैं के शरीर के साथ संघर्ष कर रहा हूँ और विधि। मैं मूल रूप से exp से शरीर को पिसाना चाहता हूं, expression में उन सभी पैरामीटर को प्रतिस्थापित करें और फिर expression शरीर के अंत में और इसके अलावा इसे भी संलग्न करें।

मैं इस किया है:

var newBody = Expression.And(expression.Body,exp.Body); 

expression = expression.Update(newBody, expression.Parameters); 

लेकिन है कि इस तरह की तलाश में मेरी अभिव्यक्ति के साथ समाप्त होता है:

{ a => e.IsActive && e.IsManaged } 

वहाँ यह करने के लिए एक सरल तरीका है? या मैं उन ई को कैसे निकाल सकता हूं और उन्हें किसी के साथ बदल सकता हूं?

उत्तर

20

सरल दृष्टिकोण यहाँ, Expression.Invoke है उदाहरण के लिए:

public static Expression<Func<T, bool>> AndAlso<T>(
    Expression<Func<T, bool>> x, Expression<Func<T, bool>> y) 
{ 
    return Expression.Lambda<Func<T, bool>>(
     Expression.AndAlso(x.Body, Expression.Invoke(y, x.Parameters)), 
     x.Parameters); 
} 

यह और LINQ करने वाली वस्तुओं के लिए ठीक काम करता है LINQ करने वाली एसक्यूएल, लेकिन एफई द्वारा समर्थित नहीं है। ईएफ के लिए आपको दुख की बात है, पेड़ को फिर से लिखने के लिए एक आगंतुक का उपयोग करने की आवश्यकता होगी।

से कोड का उपयोग करना: Combining two lambda expressions in c#

public static Expression<Func<T, bool>> AndAlso<T>(
    Expression<Func<T, bool>> x, Expression<Func<T, bool>> y) 
{ 
    var newY = new ExpressionRewriter().Subst(y.Parameters[0], x.Parameters[0]).Inline().Apply(y.Body); 

    return Expression.Lambda<Func<T, bool>>(
     Expression.AndAlso(x.Body, newY), 
     x.Parameters); 
} 

या .NET 4.0 में, ExpressionVisitor का उपयोग कर:

class ParameterVisitor : ExpressionVisitor 
{ 
    private readonly ReadOnlyCollection<ParameterExpression> from, to; 
    public ParameterVisitor(
     ReadOnlyCollection<ParameterExpression> from, 
     ReadOnlyCollection<ParameterExpression> to) 
    { 
     if(from == null) throw new ArgumentNullException("from"); 
     if(to == null) throw new ArgumentNullException("to"); 
     if(from.Count != to.Count) throw new InvalidOperationException(
      "Parameter lengths must match"); 
     this.from = from; 
     this.to = to; 
    } 
    protected override Expression VisitParameter(ParameterExpression node) 
    { 
     for (int i = 0; i < from.Count; i++) 
     { 
      if (node == from[i]) return to[i]; 
     } 
     return node; 
    } 
} 
public static Expression<Func<T, bool>> AndAlso<T>(
     Expression<Func<T, bool>> x, Expression<Func<T, bool>> y) 
{ 
    var newY = new ParameterVisitor(y.Parameters, x.Parameters) 
       .VisitAndConvert(y.Body, "AndAlso"); 
    return Expression.Lambda<Func<T, bool>>(
     Expression.AndAlso(x.Body, newY), 
     x.Parameters); 
} 
+0

Dammit, बस आह्वान स्मृति में काम करने और एफई पर परीक्षण किया गया था जब यह हुआ मिला है। धन्यवाद। –

+0

@robert आईआईआरसी Invoke ईएफ पर काम नहीं करता है, तो आपको दूसरे संस्करण –

+0

का उपयोग करने की आवश्यकता होगी आपका दृष्टिकोण काम करता है लेकिन अब मेरे पास मेरे कोडबेस में आपका अद्भुत जटिल और अनचाहे रीवाइटर है। :(यह देखकर कि यह कितना स्मार्ट दिखता है, मैं इसे तब तक रखने जा रहा हूं जब तक मैं इसे समझ नहीं पाता! –

संबंधित मुद्दे