2014-02-06 71 views
6

顯然,您可以在不丟棄.NET中的堆棧跟蹤的情況下重新拋出異常。用堆棧跟蹤中的正確行號重新生成異常

然而,它似乎並不奏效。

我下面的基本用法是這樣的:

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

問題是,在throw;線,而不是原來throw new線路的線路異常的行號。

我已經在一個簡單的exe項目中進行了測試,沒有記錄到windows日誌行。它沒有什麼區別,堆棧跟蹤中總是有錯誤的行號,使其不夠用。

它爲什麼這樣做? 我如何正確使用?

+0

這不會丟失堆棧跟蹤。是什麼讓你覺得它呢?你沒有記錄或顯示'ex.ToString()'? –

+0

'InnerException'的'CallStack'中的行號是否正確? –

+0

你確定你正在使用'throw'而不是'throw ex'嗎?另請參閱http://stackoverflow.com/q/730250/11683獲取靈感。 – GSerg

回答

4

如果將其置於內部異常中,則不會丟失原始異常。

[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

但是,你鬆散的原始異常類型(儘管在你的例子中,原始和重新排除的異常都是異常類型)。 ExceptionDispatchInfo.Capture(ex).Throw()拋出原始異常類型的異常。 – wziska

3

我已經使用了以下幾年。不知道有沒有少「狡猾」的方式在更多最新的.Net框架實現它,但:

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

要使用此:

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

更新:根據@ dcastro的評論,我在4.5倒是看中了一個擴展方法(在< 4.5它仍然是一個擴展包上面的方法):

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

所以你只需要:

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

現在你可以使用'var exInfo = ExceptionDispatchInfo.Capture(ex); exInfo.Throw();' – dcastro

+0

@dcastro:不錯 - 我發現它出現在.Net 4.5 –