2015-04-21 18 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(); 
    } 
}