2011-05-08 13 views
5

मैं एक पुन: प्रयोज्य फ़ंक्शन लिखना चाहता हूं जिसे मैं सभी स्थानीय चरों का स्नैपशॉट लॉग करने के लिए किसी भी विधि में कॉल कर सकता हूं। उदाहरण के लिए:सी # पुन: प्रयोज्य फ़ंक्शन स्थानीय चर के वर्तमान मूल्य को डंप करने के लिए

void somemethod() 
    { 
     int a = 1; 
     string s = "something"; 
     dumpLocalVariables("step 1", MethodInfo.GetCurrentMethod(), this); 

     a++; 
     string t = s + "else"; 
     dumpLocalVariables("step 2", MethodInfo.GetCurrentMethod(), this); 
    } 

मैं इस तरह एक कंसोल आउटपुट प्राप्त करना चाहते हैं:

step 1 
    Int32 a = 1 
    String s = something 
step 2 
    Int32 a = 2 
    String s = something 
    String t = somethingelse 

मैं स्थानीय चर नाम की एक विशिष्ट सूची उपलब्ध कराने से बचना चाहते हैं।

निकटतम मुझे मिल सकता था MethodInfo.GetCurrentMethod().GetMethodBody().LocalVariables, लेकिन मुझे नहीं पता कि प्रतिबिंब का उपयोग करके स्थानीय चर के मूल्यों का उपयोग कैसे किया जाए।

void dumpLocalVariables(string context, MethodBase currentMethod, object obj) 
{ 
    Console.WriteLine(context); 
    MethodBody methodBody = currentMethod.GetMethodBody(); 
    foreach (LocalVariableInfo lvi in methodBody.LocalVariables) 
    { 
     string variableType = lvi.LocalType.Name; 
     // how do I get this? 
     string variableName = "variableNameHere"; 
     // how do I get this?  
     string variableValue = "variableValueHere"; 
     Console.WriteLine(" " + variableType + " " + variableName + 
      " = " + variableValue); 
    } 
} 

प्रतिबिंब API स्थिर विश्लेषण के लिए उपयुक्त है, लेकिन इस तरह गतिशील विश्लेषण के लिए नहीं। उदाहरण के लिए, dumpLocalVariables पर पहली कॉल के दौरान चरम पर नहीं है, लेकिन यह MethodBody की संपत्ति में अभी भी दिखाई देता है।

मुझे संदेह है कि एक डिबगिंग एपीआई है जिसे मैं देख रहा हूं। डेवलपर स्टूडियो ब्रेकपॉइंट पर "स्थानीय" टैब को कैसे पॉप्युलेट करता है? रनटाइम पर कुछ ऐसा करने का कोई तरीका है?

संपादित करें:

मैं ILSpy कि मेरे उदाहरण वर्ग ldloc.0 और ldloc.1 तरह आईएल कोड का उपयोग पहले और दूसरे स्थानीय चर करने के लिए प्राप्त करने के लिए देख सकते हैं।

.locals init (
    [0] int32 a 
    [1] string s 
    [2] string t 
) 

और बाद में

IL_001b: ldloc.0 // this is a 
IL_001c: ldc.i4.1 
IL_001d: add 
IL_001e: stloc.0 
IL_001f: ldloc.1 // this is s 
IL_0020: ldstr "else" 
IL_0025: call string string::Concat(string, string) 
IL_002a: stloc.2 // this is t 

शायद मैं मुझे एक ही बात करने की सुविधा देता है कि प्रॉक्सी की तरह तंत्र किसी प्रकार का इस्तेमाल कर सकते हैं? मुझे कोई फर्क नहीं पड़ता कि मेरी पुन: प्रयोज्य विधि पर कॉल गन्दा है, मुझे बस कुछ चाहिए जो मैं बिना कोड-संपादन के किसी भी कोड ब्लॉक में पेस्ट कर सकता हूं।

+1

के हिस्से के रूप GitHub पर उपलब्ध है "मुझे लगता है एक डिबगिंग एपीआई कि मैं अनदेखी कर रहा हूँ नहीं है": 'System.Diagnostics.Debugger' –

+0

@Henk: आप स्पष्ट कर सकते हैं कि ? मुझे नहीं पता था कि 'डीबगर' वर्ग के पास 'IsAttached' और' Break() 'के अलावा कुछ भी उपयोगी था। – Groo

+1

संभावित डुप्लीकेट: [क्या सी #? में रनटाइम पर स्टैक वैरिएबल की जांच करने का कोई तरीका है? (Http://stackoverflow.com/questions/5130414/is-there-a-way-to-examine-the-stack-variables -ट-रनटाइम-इन-सी), [सी # रनटाइम के दौरान सभी चर और वर्तमान मानों को कैसे डंप करें] (http://stackoverflow.com/questions/1552478/c-how-to-dump-all-variables-current- मान-दौरान-क्रम)। – Groo

उत्तर

7

इस संबंधित सवाल देखें:

Is there a simple way to obtain all the local variables in the current stack frame in C# (or CIL)

कम जवाब है: क्योंकि वे रनटाइम पर ढेर पर सीधे आवंटित कर रहे हैं आप स्थानीय चर के मूल्यों को नहीं मिल सकता है, और इस तरह नहीं कर रहे हैं प्रतिबिंब के माध्यम से उपलब्ध है। ऐसा करने का एकमात्र तरीका डीबगर एपीआई के माध्यम से है ... और यह बहुत छोटा है। इसके अलावा, यह केवल तभी काम करेगा जब आपका कस्टम डीबगर वास्तव में प्रक्रिया से जुड़ा हुआ हो।

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

static void LogVariables(); 

और

static void LogVariables(params string[] names, params object[] values); 

एक पोस्ट का निर्माण कार्य है कि एक नियमित विधानसभा बुनाई कि बाहर स्वैप पहले LogVariables दूसरे के साथ फोन कॉल जोड़े चर नाम है, लेकिन स्पष्ट रूप से उपलब्ध कराने के: मैं दो तरीकों बनाने का सुझाव विधि के लिए/मूल्य। आप मोनो सेसिल का उपयोग करके असेंबली को संशोधित करने के लिए इस दिनचर्या को लिख सकते हैं (अन्य टूल्स भी हैं जो यह कर सकते हैं)।

http://www.mono-project.com/Cecil

+0

यह अब तक का सबसे आसान जवाब है, लेकिन वह नहीं है जिसे मैं ढूंढ रहा था। मैं अभी भी कुछ ऐसी चीज के साथ आना चाहूंगा जिसे "सामान्य" तरीके से सम्मिलित और संकलित किया जा सके। – hsmiths

+0

मुझे लगता है कि कोई और विचार नहीं है इसलिए मैं इस जवाब को अनिच्छुक रूप से स्वीकार कर रहा हूं। मुझे लगता है कि पोस्ट-कंपाइल ट्विक की आवश्यकता के बिना इस तरह के लॉगिंग करने के लिए रनटाइम पर सेसिल असेंबली का उपयोग करके कुछ लिखना संभव है। – hsmiths

+0

यदि स्थानीय चर की सूची प्राप्त करना संभव है तो प्रतिबिंब द्वारा गतिशील कोड उत्पन्न करना संभव क्यों नहीं है। इसे मानों को डंप करने के लिए सबमिट करें? – devi

2

यह प्रबंधित कोड के लिए बाहरी डिबगर का उपयोग करके भी संभव है। यह कैसे किया जाता है के लिए "प्रबंधित डिबगर नमूना" देखें: http://blogs.msdn.com/b/jmstall/archive/2004/09/30/236281.aspx (नमूना और अधिक जानकारी के लिए लिंक भी शामिल है)

+0

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

0

एक custom PostSharp aspect (with IL transformation का प्रयोग करके) write minidumps पर विचार करें।

सी # में लिखी गई एक साझा डीबगिंग इंजन लाइब्रेरी। NuGet पर Microsoft.Samples.Debugging.MdbgEngine के रूप में उपलब्ध है।

PostSharp पहलू का कोड PADRE (Pluggable Automatic Debugging and Reporting Engine)repository

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