2015-01-17 7 views
9

मुझे पता है। एक समान सवाल पहले ही पूछ चुका है।विधि का नाम प्राप्त करें जो अपवाद फेंक दिया

लेकिन मैं उस से सटीक समाधान नहीं मिला है।

मेरे पास एक बटन क्लिक ईवेंट है जिसमें मेरे पास एक विधि FillCombo() है।

बटन पर क्लिक करें घटना

private void button1_Click(object sender, EventArgs e) 
{ 
     try 
     { 
      cmbTemplates.Items.Clear(); 
      lstFiles.Clear(); 
      FillCombo();     
     } 
     catch (Exception ex) 
     { 
      MethodBase site = ex.TargetSite; 
      Log(ex.ToString(), site == null ? null : site.Name);     
     } 
} 

जब मैं डिबग, मैंने पाया कि अपवाद FillCombo() विधि से होता है। इसके बाद मुझे के FillCombo के बजाय 0 मिलता है।

मैंने GetExecutingMethodName() पर एक और विधि की कोशिश की जिसका उत्तर क्रिस गेस्लरHow to get the name of the method that caused the exception प्रश्न में उत्तर दिया गया था। इसलिए मैं विधि का नाम है कि GetExecutingMethodName() विधि

Log(ex.ToString(), GetExecutingMethodName()); 

का उपयोग कर का अपवाद उत्पन्न भेजने की कोशिश की लेकिन मैं System.Windows.Forms.Control.OnClick बजाय FillCombo के रूप में परिणाम मिला।

मैं अपवाद के कारण विधि का वास्तविक नाम कैसे प्राप्त करूं?

+0

उपयोग breakpoints अपने कोड डीबग और स्टैकट्रेस – saurabh64

+1

देखो मैं Dubug मोड में पता कर सकते हैं करने के लिए। लेकिन मुझे फाइल में त्रुटियों को लॉग करने की जरूरत है। उत्पादन वातावरण में जो बैठने और डीबग करने जा रहा है !!! @ saurabh64 –

+1

आपको पूरे स्टैक ट्रेस लॉग करना चाहिए। यह आमतौर पर इस मुद्दे को निर्धारित करने के लिए पर्याप्त संदर्भ देगा। –

उत्तर

11

.net अपवाद से स्टैक ट्रेस जानकारी प्राप्त करने का समर्थन करता है। आप पहले फ्रेम (मूल) की जांच करके विधि (और इसका नाम) फ़िल्टर कर सकते हैं।

new StackTrace(ex).GetFrame(0).GetMethod().Name 

यह शायद आप बिल्कुल targetsite (जीत कब) के रूप में ही देना होगा, लेकिन आप पहले उपयोगकर्ता कोड, या अपने प्रकार का पहला फ्रेम, या जो भी आपकी आवश्यकताओं के लिए स्टैकट्रेस जांच कर सकते हैं।

उदाहरण के लिए

, अपने वर्तमान विधानसभा में अपराधी फेंकने के नाम हो रही है:

var s = new StackTrace(ex); 
var thisasm = Assembly.GetExecutingAssembly();     
var methodname = s.GetFrames().Select(f => f.GetMethod()).First(m => m.Module.Assembly == thisasm).Name; 
+0

यह 'अपवाद। लक्ष्य साइट' संपत्ति से अलग कैसे है? और वह ओपी के 'फिलकोम्बो()' विधि का नाम कैसे प्राप्त करेगा? –

+0

@ पीटर ड्यूनिहो कृपया संपादित करें देखें। अपवाद से बाहर स्टैकट्रैक सटीक आवश्यकताओं को फ़िल्टर करने के लिए प्रवेश बिंदु था। मेरे वर्तमान स्थान पर दृश्य स्टूडियो की कमी के कारण उदाहरण जोड़ने में थोड़ा धीमा था, और डॉटनेटफिड की खोज कर रहा था;) –

+0

पूरी तरह से काम कर रहा है। मैंने कोड की कोशिश की। FillCombo विधि को निष्पादित करने से पहले अपवाद होने पर मुझे इवेंट का नाम भी मिल सकता है।बहुत बहुत धन्यवाद :) @ Me.Name –

6

यह समझना महत्वपूर्ण है कि "अपवाद को फेंकने वाली विधि" का क्या अर्थ है। जब कोई अपवाद होता है, तो एक विशिष्ट विधि होती है जो वास्तव में निष्पादित होती है। सिर्फ इसलिए कि अपवाद से पहले किसी बिंदु पर, आपने अपना खुद का FillCombo() विधि बुलाया, इसका मतलब यह नहीं है कि यह तरीका अपवाद फेंक दिया गया है।

FillCombo() विधि हालांकि (यदि आप यहां परवाह करते हैं) स्टैक ट्रेस में होंगी। यही कारण है कि पूरे स्टैक ट्रेस लॉग इन करना उपयोगी है। दरअसल, मैं आम तौर पर पूरे Exception ऑब्जेक्ट को लॉग ऑन करता हूं (यानी ex.ToString(), या बस अपवाद ऑब्जेक्ट को string.Format() या इसी तरह से पास करें जो आपके लिए ToString() पर कॉल करेगा)। इसमें अपवाद प्रकार, संदेश, संपूर्ण स्टैक ट्रेस, और यहां तक ​​कि आंतरिक अपवाद जानकारी भी शामिल होगी।


GetExecutingMethodName() विधि के लिए आपको अन्य प्रश्न से प्राप्त कोड, वास्तव में यह उपयोगी IMHO नहीं है। आप ध्यान दें कि यह वास्तव में क्या करता है वर्तमान निष्पादन स्थान के स्टैक ट्रेस के माध्यम से क्रॉल करता है, जिसकी पहली विधि को GetExecutingMethodName() घोषित किया गया था, के अलावा किसी अन्य प्रकार की घोषणा की जाती है।

यह दो कारणों से अपने उद्देश्य के लिए गलत है:

  1. ऐसा लगता है कि घोषित किया है कि एक ही कक्षा में विधि जहाँ आपके Click ईवेंट हैंडलर घोषित किया जाता है। इसका मतलब है कि इवेंट हैंडलर विधि को अनदेखा किया जाता है, और इसलिए आपको उस विधि का कॉलर मिलता है, जो Control.OnClick() विधि है (यानी वह विधि जो वास्तव में घटना को उठाती है)।

सच कहूं, मुझे लगता है कि विशेष रूप से इस सवाल का जवाब अजीब लगता है, क्योंकि नेट पहले से ही वर्तमान में क्रियान्वित विधि के MethodInfo पुन: प्राप्त करने के लिए एक API प्रदान करता है: MethodBase.GetCurrentMethod। और यह क्रिस क्रिसलर कोड के कोड से अधिक विश्वसनीय है।

  1. अधिक समस्याग्रस्त, आपके पास इस विधि को उस बिंदु पर कॉल करने का अवसर नहीं है जहां अपवाद फेंक दिया गया है! सबसे अच्छा (यानी यदि आप इस सवाल से निपटते हैं कि सहायक कहां घोषित किया गया है), जो कॉल करने वाले सभी आपको बताएंगे कि आप अपने button1_Click() विधि में हैं। लेकिन आप पहले से ही यह जानते हैं, क्योंकि अपवाद को संभालने के लिए जो कोड आप लिख रहे हैं वह उस विधि में है।


आप अपने वर्तमान में क्रियान्वित विधि प्रणाली, जिसमें से पहले अपवाद घटित बुलाया गया था के नाम जानना चाहते हैं, तो आप दो तकनीकों को जोड़ सकते हैं: वर्तमान में क्रियान्वित विधि का नाम मिलता है, और फिर पारित कि उस विधि को जो Exception ऑब्जेक्ट से उस और स्टैक ट्रेस स्ट्रिंग दोनों को लेता है, और उस विधि को ट्रेस में वर्तमान में निष्पादन विधि से ठीक पहले फ्रेम खोजने के लिए स्टैक ट्रेस स्ट्रिंग को पार्स करने दें।

यह दर्द का थोड़ा सा है, लेकिन यह किया जा सकता है।

static void Main(string[] args) 
{ 
    try 
    { 
     CallForException(); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine("Exception occurred calling {0} method", GetCallForExceptionThisMethod(MethodBase.GetCurrentMethod(), e)); 
    } 
} 

private static string GetCallForExceptionThisMethod(MethodBase methodBase, Exception e) 
{ 
    StackTrace trace = new StackTrace(e); 
    StackFrame previousFrame = null; 

    foreach (StackFrame frame in trace.GetFrames()) 
    { 
     if (frame.GetMethod() == methodBase) 
     { 
      break; 
     } 

     previousFrame = frame; 
    } 

    return previousFrame != null ? previousFrame.GetMethod().Name : null; 
} 

private static void CallForException() 
{ 
    DoActualException(); 
} 

private static void DoActualException() 
{ 
    throw new NotImplementedException(); 
} 

अंत में, कि विधि इनलाइन किए जाने वाले और अन्य अनुकूलन के कारण, यहां तक ​​कि एक पूर्ण स्टैक ट्रेस कुछ अनियमितताओं हो सकता है को ध्यान में रखना: यहाँ है कि (सरल सबूत अवधारणा-का-सांत्वना कार्यक्रम) दिखाई देंगे, इसका एक उदाहरण इसमें, उस विधि का वास्तविक नाम भी नहीं है जिसमें अपवाद फेंक दिया गया था। यही कारण है कि पूरे Exception ऑब्जेक्ट को लॉगिंग करना आमतौर पर अधिक उपयोगी होता है; अधिक संदर्भ, जितना अधिक हो सकता है कि आप जो हुआ वह पुनर्निर्माण करने में सक्षम हो।

+0

यह बहुत ही जानकारीपूर्ण है। अपवाद हैंडलिंग - प्रोस और कान्स पर अच्छी तरह से समझाया गया। +1 धन्यवाद :) –

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