2010-06-15 8 views
29

को देखते हुए एकएक सदस्य प्रवेश लैम्ब्डा अभिव्यक्ति को देखते हुए यह एक विशिष्ट स्ट्रिंग प्रतिनिधित्व करने के लिए परिवर्तित पूर्ण पहुँच पथ

Expression<Func<T, object>> 

(जैसे एक्स => x.Prop1.SubProp), मैं एक स्ट्रिंग बनाना चाहते हैं "Prop1 साथ .SubProp "आवश्यक के रूप में गहराई के लिए।

एक भी पहुंच (जैसे एक्स => x.Prop1) के मामले में, मैं आसानी से के साथ ऐसा कर सकते हैं:

MemberExpression body = (expression.Body.NodeType == ExpressionType.Convert) ? (MemberExpression)((UnaryExpression)expression.Body).Operand : (MemberExpression)expression.Body; 
return body.Member.Name; 

हालांकि, अगर वहाँ गहरा नेस्टिंग, उदा x => x.Prop1.SubProp1, यह केवल सबसे गहरा घोंसला वाला नाम मिलता है, उदा। "Prop1.SubProp1" के बजाय "SubProp1"

क्या लैम्बडा अभिव्यक्ति के पूर्ण संपत्ति पथ तक पहुंचने के लिए वैसे भी है?

+0

MemberExpression.Expression पर एक नज़र डालें। आप शायद उस अभिव्यक्ति के पेड़ को तब तक चलने के लिए उपयोग कर सकते हैं जब तक कि वे सभी सदस्य एक्स्प्रेशन उदाहरण हैं। –

+0

मुझे "स्वीकृत उत्तर" चुनने में कठिनाई थी, दोनों अच्छे थे। कोई भी इस सवाल को देखकर, मैं ल्यूकएच और दान ताओ दोनों के उत्तरों को देखने की सलाह देता हूं। – Nathan

+0

संभावित डुप्लिकेट [एक स्ट्रिंग के रूप में संपत्ति प्राप्त करें, एक अभिव्यक्ति से >] (http://stackoverflow.com/questions/2789504/get-the-property-as-a-string- से-ए-एक्सप्रेशनफंक्टमोडेल-टप्रोपर्टी) – nawfal

उत्तर

34
public string GetPath<T>(Expression<Func<T, object>> expr) 
{ 
    var stack = new Stack<string>(); 

    MemberExpression me; 
    switch (expr.Body.NodeType) 
    { 
     case ExpressionType.Convert: 
     case ExpressionType.ConvertChecked: 
      var ue = expr.Body as UnaryExpression; 
      me = ((ue != null) ? ue.Operand : null) as MemberExpression; 
      break; 
     default: 
      me = expr.Body as MemberExpression; 
      break; 
    } 

    while (me != null) 
    { 
     stack.Push(me.Member.Name); 
     me = me.Expression as MemberExpression; 
    } 

    return string.Join(".", stack.ToArray()); 
} 
+1

+1: ग्रेट दिमाग एक जैसे सोचते हैं!एक छोटी सी बात: क्या आपको नहीं लगता कि यह वास्तव में 'गेटपाथ <टी, टीप्रोपर्टी> (अभिव्यक्ति > expr) परिभाषित किया जाना चाहिए? अन्यथा आप लगभग हमेशा 'कनवर्ट'/'कन्वर्ट चेक किए गए' परिदृश्य में भागने जा रहे हैं - बस क्योंकि तर्क अनावश्यक रूप से डाला जाता है। (या मुझे कुछ याद आ रहा है?) –

+1

@ डैन: हाँ, मैं सहमत हूं। असल में, मेरे संपादन से पहले मुझे 'गेटपाथ (अभिव्यक्ति > expr) के रूप में हस्ताक्षर था। मैंने इसे प्रश्न में दिखाए गए अभिव्यक्ति से मेल खाने के लिए बदल दिया। मैं इसे छोड़ दूंगा, और मुझे लगता है कि ओपी चुन सकता है कि वे कौन सा हस्ताक्षर पसंद करते हैं - विधि निकाय में कोड वैसे ही रहता है। – LukeH

+0

कोई विचार यह है कि इंडेक्स (यानी स्क्वायर ब्रैकेट) ऑपरेटर (ओं) वाली अभिव्यक्ति के साथ काम करने के लिए इसे कैसे संशोधित किया जाए? – joelmdev

6

this question पर मेरा उत्तर देखें।

सुंदर, क्या LukeH पोस्ट के रूप में ही ज्यादा एक अतिरिक्त सुविधा के साथ:

आप एक प्रकार, कहते हैं, MyClass, प्रकार int की संपत्ति MyProperty साथ है, तो आप इस लिख सकते हैं:

Expression<Func<MyClass, object>> e = x => x.MyProperty; 

यहां अभिव्यक्ति e.BodyMemberExpression है इसलिए सरल while (me != null) me = me.Expression as MemberExpression काम नहीं करेगा।

समाधान NodeType == Convert या ConvertChecked के साथ अतिरिक्त रूप से जांचना है।

अन्य परिदृश्यों के लिए खाता हो सकता है; लेकिन संपत्ति अभिव्यक्तियों की सरल श्रृंखला के लिए, यह दृष्टिकोण बहुत अच्छी तरह से काम करता है। lambda2js

केवल गुण और indexers उपयोग करते समय, परिणाम वास्तव में आप क्या जरूरत किया जाना चाहिए:

+1

जब आप अपना संपादित करते थे तो मैं 'कन्वर्ट'/'कन्वर्ट चेक' के खाते को लेने के लिए बस अपना उत्तर संपादित कर रहा था। – LukeH

+1

@LukeH: मैं क्या कह सकता हूं? स्पष्ट रूप से आप जानते हैं कि आप क्या कर रहे हैं;) –

0

आप एक परियोजना मैं जावास्क्रिप्ट को लैम्ब्डा कन्वर्ट करने के लिए बनाया है का उपयोग कर सकते हैं।

उदाहरण 1: एकल संपत्ति पथ

Expression<Func<MyClass, object>> expr = x => x.Phone; 
var js = expr.CompileToJavascript(); 
// returns: Phone 

उदाहरण 2: एक स्ट्रिंग शब्दकोश का मार्ग युक्त इंडेक्सर

Expression<Func<MyClass, object>> expr = x => x.PhonesByName["Miguel"]; 
var js = expr.CompileToJavascript(); 
// returns: PhonesByName["Miguel"] 

उदाहरण 3: परिसर पथ indexers और युक्त कई स्तरों

Expression<Func<MyClass, object>> expr = x => x.SomeProp["Miguel"].Subprop[0].A.B; 
var js = expr.CompileToJavascript(); 
// returns: SomeProp["Miguel"].Subprop[0].A.B 
संबंधित मुद्दे

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