2014-02-06 3 views
6

Sie können anscheinend eine Exception erneut auslösen, ohne den Stack-Trace in .NET zu verwerfen.Wiederholt eine Exception mit korrekten Zeilennummern im Stack-Trace

Es scheint jedoch nicht zu funktionieren.

Basisnutzung Ich bin folgende ist also:

[WebMethod] 
    public void ExceptionTest() 
    { 
     try 
     { 
      throw new Exception("An Error Happened"); 
     } 
     catch (Exception ex) 
     { 
      evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error); 
      throw; 
     } 
    } 

Problem ist, die Zeilennummer in der Ausnahme in der Linie der throw; Linie, nicht die ursprüngliche throw new Linie.

Ich habe es in einem einfachen EXE-Projekt und ohne die Protokollierung in der Windows-Protokollzeile getestet. Es macht keinen Unterschied, der Stack-Trace hat immer die falsche Zeilennummer, was ihn weniger nützlich macht.

Warum macht es das? Wie mache ich das richtig?

+0

Das verliert nicht die Stack-Trace. Was lässt dich denken, dass es so ist? Protokollieren Sie nicht oder zeigen Sie 'ex.ToString()' an? –

+0

Ist die Zeilennummer im 'CallStack' der'InnerException' korrekt? –

+0

Bist du sicher, dass du "throw" und nicht "throw ex" benutzt? Siehe auch http://StackOverflow.com/q/730250/11683 zur Inspiration. – GSerg

Antwort

4

Sie verlieren die ursprüngliche Ausnahme nicht, wenn Sie sie in die innere Ausnahme einfügen.

[WebMethod] 
public void ExceptionTest() 
{ 
    try 
    { 
     throw new Exception("An Error Happened"); 
    } 
    catch (Exception ex) 
    { 
     evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error); 
     throw new Exception("Your message", ex); 
    } 
} 
+0

Aber Sie verlieren ursprünglichen Ausnahme-Typ (obwohl in Ihrem Beispiel sowohl Original-und ReThrown-Ausnahmen vom Typ Ausnahme sind). ExceptionDispatchInfo.Capture (ex) .Throw() löst eine Ausnahme des ursprünglichen Ausnahmetyps aus. – wziska

3

Ich habe die folgenden seit Jahren verwendet. Sie wissen nicht, ob es eine weniger „vertrackt“, wie es in mehr zu erreichen, auf dem neuesten Stand .Net Frameworks aber:

public void PreserveStackTrace(Exception ex) 
{ 
    MethodInfo preserve = ex.GetType().GetMethod("InternalPreserveStackTrace", 
               BindingFlags.Instance | BindingFlags.NonPublic); 
    preserve.Invoke(ex,null); 
} 

diese benutzen:

[WebMethod] 
public void ExceptionTest() 
{ 
    try 
    { 
     throw new Exception("An Error Happened"); 
    } 
    catch (Exception ex) 
    { 
     evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error); 
     PreserveStackTrace(ex); 
     throw ex; 
    } 
} 

aktualisieren: basierend auf @ dcastro Kommentar, ich würde Phantasie eine Erweiterungsmethode in 4,5 (in < 4.5 noch eine Erweiterung Einwickeln des Verfahrens über sein könnte):

public static void ReThrow(this Exception ex) 
{ 
    var exInfo = ExceptionDispatchInfo.Capture(ex); 
    exInfo.Throw(); 
} 

So würden Sie gerade haben:

catch (Exception ex) 
    { 
     evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error); 
     ex.ReThrow(); 
    } 
+3

Heutzutage können Sie 'var exInfo = ExceptionDispatchInfo.Capture (ex); exInfo.Throw(); ' – dcastro

+0

@dcastro: Schön - ich sehe, dass es in .Net 4.5 erschienen ist –

Verwandte Themen