2011-02-28 13 views
11

मैं 'गैर-सार्वजनिक तरीकों में तोड़ने' का समाधान ढूंढने का प्रयास कर रहा हूं।कॉल स्टैक को बनाए रखने के निजी विधि को कॉल करें

मैं अपने स्वयं के पैरामीटर को पास करने के लिए RuntimeMethodInfo.InternalGetCurrentMethod(...) पर कॉल करना चाहता हूं (इसलिए मैं GetCallingMethod() लागू कर सकता हूं), या सीधे मेरे लॉगिंग दिनचर्या में RuntimeMethodInfo.InternatGetCurrentMethod(ref StackCrawlMark.LookForMyCaller) का उपयोग करें।

[MethodImpl(MethodImplOptions.NoInlining)] 
public static MethodBase GetCurrentMethod() 
{  
    StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller;  
    return RuntimeMethodInfo.InternalGetCurrentMethod(ref lookForMyCaller); 
} 

जहां InternalGetCurrentMethod घोषित किया जाता है: आंतरिक :-) GetCurrentMethod के रूप में कार्यान्वित किया जाता है।

मुझे प्रतिबिंब का उपयोग करके विधि को कॉल करने में कोई समस्या नहीं है, लेकिन यह कॉल स्टैक को गड़बड़ कर देता है और यह केवल एक चीज है जिसे संरक्षित किया जाना चाहिए, अन्यथा यह इसके उद्देश्य को हरा देता है।

क्या स्टैकट्रेस मूल (के पास कम से कम अनुमति StackCrawlMark रों है, जो LookForMe, LookForMyCaller और LookForMyCallersCaller कर रहे हैं। की दूरी के भीतर रखने का मेरा बाधाओं वहाँ प्राप्त करने के लिए मैं क्या चाहते हैं कुछ जटिल तरीका है कर रहे हैं?

उत्तर

17

अगर वहाँ एक बात मैं के बारे में सी # प्यार है, यह गतिशील तरीकों है

वे आपको हर लक्ष्य और .NET रचनाकारों के इरादे को बायपास करते हैं:।। डी

यहाँ एक (धागा सुरक्षित) समाधान है:

(एरिक Lippert, यह पढ़ कृपया नहीं ...)

enum MyStackCrawlMark { LookForMe, LookForMyCaller, LookForMyCallersCaller, LookForThread } 
delegate MethodBase MyGetCurrentMethodDelegate(ref MyStackCrawlMark mark); 
static MyGetCurrentMethodDelegate dynamicMethod = null; 

static MethodBase MyGetCurrentMethod(ref MyStackCrawlMark mark) 
{ 
    if (dynamicMethod == null) 
    { 
     var m = new DynamicMethod("GetCurrentMethod", 
      typeof(MethodBase), 
      new Type[] { typeof(MyStackCrawlMark).MakeByRefType() }, 
      true //Ignore all privilege checks :D 
     ); 
     var gen = m.GetILGenerator(); 
     gen.Emit(OpCodes.Ldarg_0); //NO type checking here! 
     gen.Emit(OpCodes.Call, 
      Type.GetType("System.Reflection.RuntimeMethodInfo", true) 
       .GetMethod("InternalGetCurrentMethod", 
        BindingFlags.Static | BindingFlags.NonPublic)); 
     gen.Emit(OpCodes.Ret); 
     Interlocked.CompareExchange(ref dynamicMethod, 
      (MyGetCurrentMethodDelegate)m.CreateDelegate(
       typeof(MyGetCurrentMethodDelegate)), null); 
    } 
    return dynamicMethod(ref mark); 
} 
[MethodImpl(MethodImplOptions.NoInlining)] 
static void Test() 
{ 
    var mark = MyStackCrawlMark.LookForMe; //"Me" is Test's _caller_, NOT Test 
    var method = MyGetCurrentMethod(ref mark); 
    Console.WriteLine(method.Name); 
} 
+0

इस सुपर शांत है। मुझे गतिशील तरीकों पर और अधिक पढ़ना होगा। एरिक लिपर्ट आपके घर पर हत्यारे के ड्रॉड्स भेज रहा है, हालांकि, मैं थोड़ी देर के लिए दरवाजे का जवाब नहीं दूंगा। –

+1

@ जस्टिन: जब तक वे सी # के साथ प्रोग्राम किए जाते हैं, मुझे पता चलेगा कि उनके साथ कैसे निपटें। >:] – Mehrdad

+0

बहुत बढ़िया ... एक आकर्षण की तरह काम करता है! और इतना आसान ... तो आखिरकार मैं लॉगिंग विधि में System.Reflection.MethodBase.GetCurrentMethod() को पास किए बिना विधि को लॉग कर सकता हूं! मैं निश्चित रूप से इसे अन्य स्थानों में प्रतिबिंब प्रतिस्थापन के रूप में भी कोशिश करूंगा। बीटीडब्ल्यू: समाधान पढ़ने वालों के लिए: नए डायनेमिक मोडर कन्स्ट्रक्टर को दिया गया विधि नाम आपको पसंद है। – Edwin

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