2012-06-22 36 views
9

में पैरामीटर बदलें इस कोड को ध्यान में रखते हुए:लैम्ब्डा अभिव्यक्ति

public class Foo 
{ 
    public int a { get; set; } 
    public int b { get; set; } 
} 

private void Test() 
{ 
    List<Foo> foos = new List<Foo>(); 
    foos.Add(new Foo()); 
    foos.Add(new Foo()); 
    Expression<Func<Foo, int>> exp0 = f => f.a * f.b; 
    Expression<Func<int>> exp1 =() => foos[0].a * foos[0].b; 
    Expression<Func<int>> exp2 =() => foos[1].a * foos[1].b; 
} 

कैसे आप exp0 लेते हैं और इसे दो भाव exp1 और exp2 के समान में बदल सकते हैं। ध्यान दें कि मैं में प्रत्येक Foo के लिए exp0 का मूल्यांकन नहीं करना चाहता, बल्कि इसके बजाय दो नए भाव प्राप्त करें।

[अपडेट]:

मूल रूप से, मैं एक अभिव्यक्ति एक Linq विस्तार विधि के लिए पारित विस्तार करने के लिए या "समतल" सक्षम होना चाहते हैं इस तरह के रूप में इन enumerations के बाद से गणन में आइटम प्रति एक अभिव्यक्ति में Sum होगा स्थैतिक रहें, और क्योंकि मेरे पास पहले से कोड है जो अभिव्यक्ति पढ़ता है जो पैरामीटर नहीं लेता है (और फिर उन्हें दूसरी भाषा में बदल देता है)।

मैं गुण एक निश्चित विशेषता है (इस मामले में a और b इस विशेषता के लिए होता है) के लिए एक संदर्भ के रूप में MetadataToken उपयोग कर रहा हूँ और एक शब्दकोश है कि किसी अन्य भाषा के चर के सी # गुण संबद्ध के साथ इसे का उपयोग:

एक पैरामीटर-replacer अभिव्यक्ति-आगंतुक है कि मूल अभिव्यक्ति manipulates इस प्रकार लिखें:

Foo foo = new Foo(); 
Expression<Func<int>> exp =() => foo.a * foo.a + foo.b; 
string result1 = GetResult(exp); // gets "v_001 * v_001 + v_002" 

List<Foo> foes = new List<Foo>(); 
foes.Add(new Foo()); 
foes.Add(new Foo()); 
Expression<Func<int>> exp2 =() => foes.Sum(f => f.a * f.a + f.b); 
string result2 = GetResult(exp2); // should get "(v_001 * v_001 + v_002) + (v_003 * v_003 + v_004)" 
+0

आप हमें एक दे सकते हैं उदाहरण के लिए आप इसका उपयोग कैसे करेंगे और आउटपुट क्या होगा? –

+0

यह भी देखें http://stackoverflow.com/questions/5631070/currying-expressions-in-c-sharp – AakashM

उत्तर

15

मैं इसे इस तरह से करना होगा

  1. उस पैरामीटर से छुटकारा पाता है जिसे आप पूरी तरह से लैम्ब्डा हस्ताक्षर से नहीं चाहते हैं।
  2. वांछित अनुक्रमणिका अभिव्यक्ति के साथ पैरामीटर के सभी उपयोगों को प्रतिस्थापित करता है।

यहाँ एक त्वरित और गंदी नमूना मैं के आधार पर मार पड़ी है मेरी earlier answer एक अलग प्रश्न पर: अपने परिदृश्य (परीक्षण किया) के लिए

public static class ParameterReplacer 
{ 
    // Produces an expression identical to 'expression' 
    // except with 'source' parameter replaced with 'target' expression.  
    public static Expression<TOutput> Replace<TInput, TOutput> 
        (Expression<TInput> expression, 
        ParameterExpression source, 
        Expression target) 
    { 
     return new ParameterReplacerVisitor<TOutput>(source, target) 
        .VisitAndConvert(expression); 
    } 

    private class ParameterReplacerVisitor<TOutput> : ExpressionVisitor 
    { 
     private ParameterExpression _source; 
     private Expression _target; 

     public ParameterReplacerVisitor 
       (ParameterExpression source, Expression target) 
     { 
      _source = source; 
      _target = target; 
     } 

     internal Expression<TOutput> VisitAndConvert<T>(Expression<T> root) 
     { 
      return (Expression<TOutput>)VisitLambda(root); 
     } 

     protected override Expression VisitLambda<T>(Expression<T> node) 
     { 
      // Leave all parameters alone except the one we want to replace. 
      var parameters = node.Parameters 
           .Where(p => p != _source); 

      return Expression.Lambda<TOutput>(Visit(node.Body), parameters); 
     } 

     protected override Expression VisitParameter(ParameterExpression node) 
     { 
      // Replace the source with the target, visit other params as usual. 
      return node == _source ? _target : base.VisitParameter(node); 
     } 
    } 
} 

उपयोग:

var zeroIndexIndexer = Expression.MakeIndex 
     (Expression.Constant(foos), 
     typeof(List<Foo>).GetProperty("Item"), 
     new[] { Expression.Constant(0) }); 


// .ToString() of the below looks like the following: 
// () => (value(System.Collections.Generic.List`1[App.Foo]).Item[0].a 
//   * value(System.Collections.Generic.List`1[App.Foo]).Item[0].b) 
var exp1Clone = ParameterReplacer.Replace<Func<Foo, int>, Func<int>> 
        (exp0, exp0.Parameters.Single(), zeroIndexIndexer); 
+1

नेस्टेड लैम्बडास के लिए, मैंने पाया कि मुझे अभिव्यक्ति के बजाय अभिव्यक्ति का उपयोग करना चाहिए। लैम्ब्डा 0 ...(। ..)। किसी भी मामले में प्रकार पैरामीटर संस्करण अनावश्यक लगता है। – HappyNomad

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