2012-05-16 24 views
13

मैं दो लैम्ब्डा भाव है:मैं Invoke विधि का उपयोग किये बिना दो लैम्ब्डा अभिव्यक्तियों को कैसे जोड़ सकता हूं?

Expression<Func<MyEntity, bool>> e1 = i=>i.FName.Contain("john");

और

Expression<Func<MyEntity, bool>> e2=i=>i.LName.Contain("smith"); 

मैं प्रकार, मेरे पोको संस्थाओं, कि आह्वान के साथ उपयोग नहीं कर सकते हैं से आता है। मैं इन्हें रनटाइम में जोड़ना चाहता हूं।

मैं के रूप में एक समान तरीके से क्रम में इन भाव संयोजित करना चाहते हैं:

Expression<Func<MyEntity, bool>> e3 = Combine(e1,e2); 
+0

कम्बाइन * कैसे * - "और"? –

+0

हां, और साथ ही। मैं इन्हें रनटाइम में जोड़ना चाहता हूं। – PickleRick

उत्तर

35
समस्या

है कि आप बस "और"/"या" उन्हें, क्योंकि आप फिर से लिखने की जरूरत नहीं कर सकते हैं पैरामीटर बदलने के लिए आंतरिक; यदि आप e2 से e1 से .Body, लेकिन पैरामीटर उपयोग करते हैं, यह काम नहीं करेगा - क्योंकि e1 की .Body संदर्भ पूरी तरह से असंबद्ध पैरामीटर उदाहरण है कि परिभाषित नहीं है। यह वह जगह है अधिक स्पष्ट अगर आप का उपयोग करें:

Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john"); 
Expression<Func<MyEntity, bool>> e2 = j => j.LName.Contains("smith"); 

(j का उपयोग कर i और e2 का उपयोग कर e1 के बीच अंतर पर ध्यान दें) तो हम उन्हें पैरामीटर को फिर से लिखने के बिना गठबंधन है, हम अतर्कसंगत मिलेगा:

Expression<Func<MyEntity, bool>> combined = 
     i => i.FName.Contains("john") && j.LName.Contains("smith"); 

(ओह .... जहां j से आया?)

हाउवर; समस्या पैरामीटर के नाम नाम पर समान है: यह अभी भी एक अलग पैरामीटर है।

और चूंकि अभिव्यक्ति अपरिवर्तनीय है, इसलिए आप इसे "जगह में" स्वैप नहीं कर सकते हैं।

चाल तो जैसे नोड्स के पुनर्लेखन के लिए, एक "आगंतुक" का उपयोग करने के लिए है:

using System; 
using System.Linq.Expressions; 

class SwapVisitor : ExpressionVisitor 
{ 
    private readonly Expression from, to; 
    public SwapVisitor(Expression from, Expression to) 
    { 
     this.from = from; 
     this.to = to; 
    } 
    public override Expression Visit(Expression node) 
    { 
     return node == from ? to : base.Visit(node); 
    } 
} 

static class Program 
{ 
    static void Main() 
    { 
     Expression<Func<MyEntity, bool>> e1 = i => i.FName.Contains("john"); 
     Expression<Func<MyEntity, bool>> e2 = i => i.LName.Contains("smith"); 

     // rewrite e1, using the parameter from e2; "&&" 
     var lambda1 = Expression.Lambda<Func<MyEntity, bool>>(Expression.AndAlso(
      new SwapVisitor(e1.Parameters[0], e2.Parameters[0]).Visit(e1.Body), 
      e2.Body), e2.Parameters); 

     // rewrite e1, using the parameter from e2; "||" 
     var lambda2 = Expression.Lambda<Func<MyEntity, bool>>(Expression.OrElse(
      new SwapVisitor(e1.Parameters[0], e2.Parameters[0]).Visit(e1.Body), 
      e2.Body), e2.Parameters); 
    } 
} 
+0

+1 वाह - क्या एक अंतर्दृष्टिपूर्ण जवाब है। –

+0

धन्यवाद मार्क! आपने कर दिखाया। यह बहुत अच्छा काम करता है। – PickleRick

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

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