2009-02-06 13 views
23

के MethodInfo से होस्टिंग PropertyInfo को ढूँढना मैं प्रतिबिंब का उपयोग कर रनटाइम में कुछ प्रकार का विश्लेषण करता हूं। अगर मेरे पास MethodInfo उदाहरण है, यह कैसे पता लगा सकता है कि यह एक "असली" विधि है या संपत्ति का गेटटर/सेटर विधि है? और यदि यह एक संपत्ति है, तो मैं अपनी होस्टिंग PropertyInfo को वापस कैसे ढूंढ सकता हूं?गेटटर/सेटर

उत्तर

7

एक्मा 335 निर्दिष्ट करता है (लेकिन मांग नहीं करता है) कि कंपाइलर get_/set_ उपसर्ग (अध्याय 22.28) का उपयोग करते हैं। मुझे ऐसी कोई भी भाषा नहीं है जो उस सिफारिश को तोड़ देती है। यह आसान बनाना:

public static PropertyInfo GetPropFromMethod(Type t, MethodInfo method) { 
    if (!method.IsSpecialName) return null; 
    return t.GetProperty(method.Name.Substring(4), 
    BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); 
} 
+2

सूचनात्मक पाठ से, यह सीएलएस अनुपालन होना आवश्यक है, लेकिन वैध आईएल होने की आवश्यकता नहीं है। –

+1

मैं इस तरह से जाने की सिफारिश नहीं करता। मैं सभी गुणों की जांच करने की सलाह देते हैं। स्ट्रिंग पैटर्न सम्मेलन - मजबूत नहीं। –

+1

मुझे एक काउंटर उदाहरण देखना अच्छा लगेगा। –

17

ठीक है, गेटर और सेटर के पीछे की विधि "असली" विधियां हैं।

पुन: संपत्ति को वापस ट्रैक करना - पैटर्न (वापसी बनाम 1 तर्क) इसे संकीर्ण करने में मदद करेगा - लेकिन आपको संपत्ति खोजने के लिए प्रत्येक पर GetGetMethod/GetSetMethod कॉल करना होगा।

आप शायदName (कम __/set__ प्राप्त करें) आज़माएं - लेकिन यह भंगुर लगता है।

static PropertyInfo GetProperty(MethodInfo method) 
{ 
    bool takesArg = method.GetParameters().Length == 1; 
    bool hasReturn = method.ReturnType != typeof(void); 
    if (takesArg == hasReturn) return null; 
    if (takesArg) 
    { 
     return method.DeclaringType.GetProperties() 
      .Where(prop => prop.GetSetMethod() == method).FirstOrDefault(); 
    } 
    else 
    { 
     return method.DeclaringType.GetProperties() 
      .Where(prop => prop.GetGetMethod() == method).FirstOrDefault(); 
    } 
} 
+0

वर्कअराउंड के लिए +1, अभी भी 'name.StartsWith ("get_"/"set_") पसंद करते हैं। – arul

+0

हम्म ... शायद सी # कोड के लिए, कम से कम ... उनका उल्लेख ईसीएमए 335 के 17.2.7.1 में किया गया है - लेकिन क्या यह अन्य भाषाओं पर लागू है? मैं ईसीएमए 334 की जांच करूंगा ... –

+0

निश्चित रूप से, खंड 17.2.7.1 देखें। एक संपत्ति के लिए पी प्रकार टी, निम्नलिखित हस्ताक्षर आरक्षित हैं: टी get_P(); शून्य सेट_P (टी मान); दोनों हस्ताक्षर आरक्षित हैं, भले ही संपत्ति केवल पढ़ने या लिखने के लिए ही हो। – arul

5

MethodBase.IsSpecialName में देखो: यहाँ अब संस्करण (Name का कोई उपयोग नहीं) है। विधि जो स्पष्ट रूप से दिखाई नहीं देनी चाहिए, जैसे कि संपत्ति एक्सेसर्स, ईवेंट सदस्यता विधियां और ऑपरेटर ओवरलोड इस ध्वज का उपयोग करते हैं।

मेरे ज्ञान के लिए, गुणों के माध्यम से पुन: प्रयास किए बिना और विधियों की तुलना किए बिना PropertyInfo खोजने का कोई तरीका नहीं है।

+0

एमएस के मुताबिक, आप गारंटी नहीं दे सकते कि IsSpecialName ध्वज सेट किया जाएगा: http://connect.microsoft.com/VisualStudio/feedback/details/108302/for-property-accessors-get-set-isspecialname-false –

+0

IsSpecialName हालांकि काम करने के लिए प्रतीत होता है। मुझे उम्मीद है कि यह कुछ एमएस बदल गया है क्योंकि यह स्पष्ट करने के बजाय ध्वज की जांच करने में सक्षम होना बेहतर है कि कौन सी भाषा विशेषताओं को लागू किया जा सकता है (संभावित रूप से अनमार्क किए गए) विशेष तरीकों के रूप में। –

5

मैं वास्तव में एक टिप्पणी के रूप में इस छोड़ना चाहते हैं, लेकिन मैं अपने प्रतिनिधि नहीं है पर्याप्त उच्च के बाद से नहीं कर सकते :(

मार्क Gravell के कोड में एक बग Theres: अगर इसकी एक इंडेक्सर ऐसा लगता है कि जल्दी विफल करने के लिए अशक्त वापस आ जाएगी, तब भी जब एक माता पिता संपत्ति मौजूद है इसका अच्छा है, लेकिन मुझे लगता है कि हम केवल ऐसा कर सकते हैं जब यह न तो एक वापसी मान या एक पैरामीटर है:।

[Pure] 
    public static PropertyInfo GetParentProperty(this MethodInfo method) 
    { 
     if (method == null) throw new ArgumentNullException("method"); 
     var takesArg = method.GetParameters().Length == 1; 
     var hasReturn = method.ReturnType != typeof(void); 
     if (!(takesArg || hasReturn)) return null; 

     if (takesArg && !hasReturn) 
     { 
      return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetSetMethod() == method); 
     } 
     else 
     { 
      return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetGetMethod() == method); 
     } 
    } 
-1

चाल करने के लिए बाध्यकारीफ्लैग्स के साथ खेलें। केवल और IsSpecialName