2012-03-04 10 views
6

मैं निष्पादन संपत्ति का संपत्ति नाम कैसे प्राप्त करूं। यदि संपत्ति "वापसी" का उपयोग करती है तो MethodBase.GetCurrentMethod()। नाम संपत्ति का नाम देता है। लेकिन जब मैं "उपज रिटर्न" का उपयोग करता हूं MethodBase.GetCurrentMethod()। नाम "MoveNext" देता है। उपज रिटर्न का उपयोग करते समय मैं निष्पादन संपत्ति का नाम कैसे प्राप्त करूं?उपज रिटर्न का उपयोग करते समय संपत्ति का नाम कैसे प्राप्त करें

नमूना कोड

class Program 
    { 
     static void Main(string[] args) 
     { 

     var x = myProgram.Something; 

     Console.ReadLine(); 
     }  
    } 

public class myProgram 
{ 
    public static IEnumerable<string> Something 
    { 
     get 
     { 
      string var = MethodBase.GetCurrentMethod().Name; 
      for (int i = 0; i < 5; i++) 
      { 
       yield return var; 
      } 
     } 
    } 
} 
+4

उपयोग मामला है क्या के भविष्य के संस्करणों में काम नहीं कर सकता है? अगर हम आवश्यकता और संदर्भ को समझते हैं, तो हम शायद आपको बेहतर तरीके से मदद कर सकते हैं। – jason

+1

आप क्या हासिल करने की कोशिश कर रहे हैं? – Lloyd

+0

@ जेसन, मैं कुछ उपयोग मामलों के बारे में सोच सकता हूं - इनमें से केवल एक लॉगिंग होगा। यह एक अच्छा सवाल है – kelloti

उत्तर

5

आप शायद देखा है के रूप में, संकलक कैसे reorganizes: चूंकि CallerMemberName विशेषता संकलन समय पर हल हो गई है, और जाहिरा तौर पर पहले इटरेटर एक प्रगणक वर्ग में फिर से लिखा गया है, यह संपत्ति के नाम का उत्पादन तरीके काम करते हैं और कुछ एक निजी वर्ग लौटाता है जो IEnumerable लागू करता है। इस प्रकार, आपकी विधि की वास्तविक सामग्री MoveNext इस निजी श्रेणी की विधि में दिखाई देती है, इसलिए MethodBase.GetCurrentMethod ऐसा नहीं लगता है कि ऐसा लगता है कि इसे वापस करना चाहिए।

ऐसा होता है कि निजी वर्ग का नाम मूल विधि नाम से लिया गया है, जो इस मामले में <Enumerate>d__0 है। तो, आप मूल विधि नाम को स्टैक फ्रेम से पार्स कर सकते हैं।

static IEnumerable<string> Enumerate() 
{ 
    var method = new StackTrace(true).GetFrame(0).GetMethod().DeclaringType.Name; 
    yield return Regex.Replace(method, @".*<([^)]+)>.*", "$1"); 
} 

static void Main(string[] args) 
{ 
    foreach (var @string in Enumerate()) 
    { 
     Console.WriteLine(@string); 
    } 
} 

यह जाहिर है, एक हैक है और आसानी से नेट

+0

नाम वास्तव में obfuscated नहीं है।Obfuscation जानबूझकर कोड को छिपाने की कोशिश कर रहा है, जो यहां नहीं होता है। इस तरह के नाम को "अनपेक्षित" कहा जाता है, क्योंकि वे मान्य सी # नाम नहीं हैं। साथ ही, आपको 'StackTrace' का उपयोग करने की आवश्यकता नहीं है,' MethodBase.GetCurrentMethod() 'पर्याप्त है। – svick

+0

@svick मुझे लगता है कि आपका अधिकार है, मैंने इसे संपादित किया है – kelloti

+0

मदद के लिए धन्यवाद मैं अब स्टैकट्रस दृष्टिकोण के साथ जा रहा हूं क्योंकि यह जानकर कि यह एक हैक है। – kumar

1

मैं एक सहायक विधि में इटरेटर कदम होगा:

public class myProgram 
{ 
    public static IEnumerable<string> Something 
    { 
     get 
     { 
      string var = MethodBase.GetCurrentMethod().Name; 
      return GetSomethingInternal(); 
     } 
    } 

    private static IEnumerable<string> GetSomethingInternal() 
    { 
     for (int i = 0; i < 5; i++) 
     { 
      yield return i; 
     } 
    } 
} 
5

आप शायद अनुमान लगा सकते हैं, समस्या यह है कि एक yield return बयान के पीछे को फिर से लिखने का एक सा करता है दृश्य, using या लैम्ब्डा अभिव्यक्ति कैसे करता है। यह वास्तव में गणनाकर्ता के रूप में कार्यान्वित किया जाता है, जो yield return को MoveNext विधि का हिस्सा होने वाले कोड के साथ गणना करता है।

यह प्रतिबिंब का उपयोग करने का एक समग्र समस्या है: यह है कि आप अपने को क्रियान्वित करने के बारे में कोड क्रम जानकारी है, जो अपने संकलन समय क्या है कि कोड था की विचार से मेल न खाए देता है।

यह कहने का एक लंबा रास्ता है कि आपके इच्छित जानकारी प्राप्त करने का कोई आसान तरीका नहीं है। यदि आप yield return को एक अलग विधि में आगे ले जाना चाहते हैं, तो उस विधि के बाहर कोई भी कोड MoveNext का हिस्सा नहीं होगा, लेकिन जो आपको चाहिए वह पूरा हो सकता है या नहीं भी हो सकता है। अब आपको yield return निष्पादित करने वाली विधि का नाम नहीं मिल रहा है, आपको इसका नाम कॉलर का नाम मिल रहा है। यदि यह सब आप के बारे में परवाह है, यह इस तरह दिखता है:

public IEnumerable<string> Something 
{ 
    get 
    { 
     var x = MethodBase.GetCurrentMethod().Name; 
     return this.DoSomething(x); 
    } 
} 

private IEnumerable<string> DoSomething(string x) 
{ 
    for (int i = 0; i < 5; i++) 
    { 
     yield return x; 
    } 
} 

संपादित करें: मुझे शक है यह अल्पावधि में मदद मिलेगी, रिकार्ड के लिए करते हैं, इस समस्या को भी जब सी # 5 की नई विशेषताओं का उपयोग हल किया जाता है।

public IEnumerable<string> Something 
{ 
    get 
    { 
     var x = this.GetCallerName(); 
     for (int i = 0; i < 5; i++) 
     { 
      yield return x; 
     } 
    } 
} 

private string GetCallerName([CallerMemberName] string caller = null) 
{ 
    return caller; 
} 
+0

जानकारी के लिए धन्यवाद कॉलरमम्बरनाम के लिए नजर रखेगा। अन्य बाधाओं के कारण मैं स्टैकट्रेस समाधान के साथ जा रहा हूं। – kumar

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