2015-04-21 57 views
2

我正在爲某件軟件構建工具,並且希望能夠保存Debug.Assert(或Trace.Assert)調用中存在的源代碼中的布爾表達式。將Debug.Assert條件作爲失敗的字符串獲取

例如,如果程序崩潰與:

var x = -1; 
Debug.Assert(x >= 0, "X must be non-negative", "some detail message"); 

我希望能夠走出串"x >= 0"以及消息和詳細消息。

我已經研究過使用TraceListener,但TraceListener#Fail(string)TraceListener#Fail(string, string)只能捕捉消息和詳細消息字段(其中,在該情況下,開發商不包括,給我留下了沒有簡單的方法來報告什麼地方出了錯) 。

我想有可能創建一個堆棧跟蹤並讀取失敗的特定行並報告(假設源代碼可用),但這似乎相對脆弱。

謝謝你的時間!

+3

也許創造一個表達,通過在表達式中斷言,那麼如果它沒有從表達構建您的字符串。 – paqogomez

+0

如果其中一個答案充分解決了您的問題,您可能需要選擇它作爲答案,以便可以從「未答覆」列表中刪除此問題。 – Alex

+0

抱歉,延遲。儘管所有涉及傳遞表達式的答案都可以工作,但我不幸的是無法通過並更改許多現有的'Debug.Assert'語句並強制實施新的開發人員實踐......也許我可以做一些代碼轉換,但這可能會導致[可能]評估斷言條件表達式的不必要成本(可能在特殊的「真正的調試」構建?) –

回答

2

您可以使用表達式來粗略有所建樹:

public static class DebugEx 
{ 
    [Conditional("DEBUG")] 
    public static void Assert(Expression<Func<bool>> assertion, string message) 
    { 
     Debug.Assert(assertion.Compile()(), message, assertion.Body.ToString()); 
    } 
} 

,並使用它,像這樣:

var i = -1; 
DebugEx.Assert(() => i > 0, "Message"); 

有一些向下雙方本。首先是,你必須使用lambda,這樣會使語法複雜一點。第二個是因爲我們正在動態編譯東西,所以性能受到影響。由於這隻會發生在調試模式(因此有條件),所以在發佈模式下不會看到性能損失。

最後,輸出並不漂亮。它會是這個樣子:

(值(WindowsFormsApplication1.Form1 + <> c__DisplayClass0).I> 0)

沒有了一大堆你可以做這件事。發生這種情況的原因是因爲關閉了i。這實際上是準確的,因爲這是它被編譯進去的。

2

當@vcsjones發佈他的answer時,我已經開始輸入答案,所以我放棄了我的,但我看到它的一些部分仍然相關。主要是關於將lambda表達式格式化爲可讀的內容,所以我會將他與我想要的答案的那部分合並。

它使用了許多正則表達式來設置斷言表達式的格式,所以在很多情況下它看起來不錯(即接近你輸入的內容)。

對於@vcsjones給出的例子回答它現在看起來就像這樣:

斷言 '(I> 0)' 失敗。

public static class DebugEx 
{ 
    private static readonly Dictionary<Regex, string> _replacements; 

    static DebugEx() 
    { 
     _replacements = new Dictionary<Regex,string>() 
     { 
      {new Regex("value\\([^)]*\\)\\."), string.Empty}, 
      {new Regex("\\(\\)\\."), string.Empty}, 
      {new Regex("\\(\\)\\ =>"), string.Empty}, 
      {new Regex("Not"), "!"} 
     }; 
    } 

    [Conditional("DEBUG")] 
    public static void Assert(Expression<Func<bool>> assertion, string message) 
    { 
     if (!assertion.Compile()()) 
      Debug.Assert(false, message, FormatFailure(assertion)); 
    } 

    private static string FormatFailure(Expression assertion) 
    { 
     return string.Format("Assertion '{0}' failed.", Normalize(assertion.ToString())); 
    } 

    private static string Normalize(string expression) 
    { 
     string result = expression; 
     foreach (var pattern in _replacements) 
     { 
      result = pattern.Key.Replace(result, pattern.Value); 
     } 
     return result.Trim(); 
    } 
}