2008-10-26 5 views
30

मैं एक अभिव्यक्ति वृक्ष पार्स कर रहा हूं। ExpressionType.MemberAccess के एक नोड टाइप को देखते हुए, मुझे उस फ़ील्ड का मूल्य कैसे प्राप्त होगा?एक प्रकार दिया गया ExpressionType.MemberAccess, मैं फ़ील्ड मान कैसे प्राप्त करूं?

सी # एमएसडीएन दस्तावेज़ों से: सदस्य पहुंच एक नोड है जो किसी क्षेत्र या संपत्ति से पढ़ने का प्रतिनिधित्व करता है।

एक कोड स्निपेट अविश्वसनीय रूप से अविश्वसनीय रूप से सहायक होगा। अग्रिम में धन्यवाद!!!

मेरे कोड इस तरह दिखता है:

public static List<T> Filter(Expression<Func<T, bool>> filterExp) 
{ 
//the expression is indeed a binary expression in this case 
BinaryExpression expBody = filterExp.Body as BinaryExpression; 

if (expBody.Left.NodeType == ExpressionType.MemberAccess) 
    //do something with ((MemberExpressionexpBody.Left).Name 

//right hand side is indeed member access. in fact, the value comes from //aspdroplist.selectedvalue    
if (expBody.Right.NodeType == ExpressionType.MemberAccess) 
{ 
    //how do i get the value of aspdroplist.selected value?? note: it's non-static       
} 

//return a list 
} 

उत्तर

38

[स्पष्टता के लिए अद्यतन]

पहले; Expression को MemberExpression पर डालें। - PropertyInfo/FieldInfo सदस्य

  • .Expression करने के लिए - "obj" .Member
  • के लिए प्राप्त करने के लिए मूल्यांकन करने के लिए अभिव्यक्ति

    • .Member:

      एक MemberExpression ब्याज की दो बातें है

    यानी अगर आप .Expression को "obj" मूल्यांकन कर सकते हैं, और .Member एक FieldInfo है, तो आप .GetValue(obj) पर के माध्यम से वास्तविक मूल्य प्राप्त कर सकते हैं FieldInfo (और PropertyInfo बहुत समान है)।

    समस्या यह है कि .Expression का मूल्यांकन बहुत मुश्किल ;-p

    जाहिर है कि आप जीत जाएं, तो यह पता चला है एक ConstantExpression हो रहा है है - लेकिन ज्यादातर मामलों में यह नहीं है, यह ParameterExpression हो सकता है (जिस स्थिति में आपको वास्तविक पैरामीटर मान जानने की आवश्यकता होगी जिसे आप मूल्यांकन करना चाहते हैं), या Expression एस के किसी भी अन्य संयोजन।

    कई मामलों में, भारी उठाने के लिए .NET ढांचे को प्राप्त करने के लिए .Compile() का उपयोग करने के लिए एक साधारण (शायद आलसी) विकल्प का उपयोग करना है; फिर आप लैम्ब्डा को एक टाइप किए गए प्रतिनिधि के रूप में मूल्यांकन कर सकते हैं (लैम्ब्डा की आवश्यकता वाले किसी भी पैरामीटर में गुजरना)। हालांकि, यह हमेशा एक विकल्प नहीं है।

    यह दिखाने के लिए कि यह कितना जटिल है; इस तुच्छ उदाहरण पर विचार करें (जहां मैं हर कदम पर हार्ड-कोडेड है, कृपया आदि के परीक्षण की तुलना में):

    using System; 
    using System.Linq.Expressions; 
    using System.Reflection; 
    class Foo 
    { 
        public string Bar { get; set; } 
    } 
    
    static class Program 
    { 
        static void Main() 
        { 
         Foo foo = new Foo {Bar = "abc"}; 
         Expression<Func<string>> func =() => foo.Bar; 
    
         MemberExpression outerMember = (MemberExpression)func.Body; 
         PropertyInfo outerProp = (PropertyInfo) outerMember.Member; 
         MemberExpression innerMember = (MemberExpression)outerMember.Expression; 
         FieldInfo innerField = (FieldInfo)innerMember.Member; 
         ConstantExpression ce = (ConstantExpression) innerMember.Expression; 
         object innerObj = ce.Value; 
         object outerObj = innerField.GetValue(innerObj); 
         string value = (string) outerProp.GetValue(outerObj, null);  
        } 
    
    } 
    
    +0

    आपको बहुत धन्यवाद मार्क। .xpression संपत्ति का यह मूल्य है ... कुछ और दिलचस्प: \t {मान (ASP.usercontrols_mycontro_ascx) .controlname} –

    +0

    मैं जेनेरिक और प्रतिबिंब के साथ बहुत कुछ कर रहा हूं इसलिए propertyinfo/fieldinfo के माध्यम से मूल्य पुनर्प्राप्त करना काम नहीं कर रहा है क्योंकि मैं मुझे यकीन नहीं है कि संदर्भ वस्तु को कहां से खींचें ... क्या मैं इसे memberexpression या methodinfo से खींच सकता हूं? –

    +1

    यह काम करेगा ... लेकिन समस्या यह है कि आपको मूल्यांकन करने की आवश्यकता है।FieldInfo/PropertyInfo के लिए "obj" के रूप में फ़ीड करने के लिए मूल्य के रूप में अभिव्यक्ति। क्या आप सिर्फ कॉम्पाइल() का उपयोग नहीं कर सकते हैं और लैम्ब्डा को प्रतिनिधि के रूप में निष्पादित कर सकते हैं? पार्सिंग से बहुत आसान ... –

    21

    आप ऊपर मार्क Gravell के लिए इतना बहुत बहुत धन्यवाद। मैंने वास्तव में उसकी मदद की सराहना की।

    यह मेरे मामले में पता चला है। समस्या के माध्यम से हल किया जा सकता है:

    object value = Expression.Lambda(expBody.Right).Compile().DynamicInvoke(); 
    

    धन्यवाद फिर से मार्क!

    +0

    के साथ अपडेट करने जा रहा हूं जो मुझे चाहिए! –

    +5

    या बेहतर 'ऑब्जेक्ट वैल्यू = एक्सप्रेशन.लैम्ब्डा > (अभिव्यक्ति। कन्वर्ट (एक्सपोडी.राइट, टाइपऑफ (ऑब्जेक्ट)))। संकलित()। Invoke()' –

    +0

    दुखद हिस्सा: यह बहुत धीमा है। – ren

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