我试图在.net(c#)中添加一个未处理的异常处理程序,该处理程序对于'user'应该尽可能有用.最终用户大多是程序员,所以他们只需要暗示他们操纵错误的对象.
当应用程序崩溃时,我正在开发类似于Windows XP错误报告的窗口,但是尽可能多地提供关于抛出的异常的中间信息.
虽然堆栈跟踪使我(因为我有源代码)能够查明问题的根源,但是用户没有它,因此它们在没有进一步信息的情况下丢失.不用说我必须花很多时间来支持这个工具.
有一些系统异常,如Dictionary集合抛出的KeyNotFoundException,它真的让我感到烦恼,因为它们没有在消息中包含未找到的密钥.我可以使用大量的try catch块来填充我的代码,但它相当激进并且需要维护更多的代码,更不用说更多的字符串必须最终被本地化.
最后一个问题:有没有办法获得(在运行时)调用堆栈跟踪中每个函数的参数值?仅这一点就可以解决90%的支持电话.
我不认为System.Diagnostics.StackFrame提供参数信息(方法签名除外).
您可以通过AOP跟踪日志记录来检测麻烦的调用,甚至可以使用其异常拦截功能有条件地记录而不必乱丢您的代码.浏览http://www.postsharp.org/.
同样,我没有找到任何在运行时自动派生参数的东西.相反,我使用Visual Studio加载项生成明确打包参数的代码,如下所示:
public class ExceptionHandler { public static bool HandleException(Exception ex, IList parameters) { /* * Log the exception * * Return true to rethrow the original exception, * else false */ } } public class Param { public string Name { get; set; } public object Value { get; set; } } public class MyClass { public void RenderSomeText(int lineNumber, string text, RenderingContext context) { try { /* * Do some work */ throw new ApplicationException("Something bad happened"); } catch (Exception ex) { if (ExceptionHandler.HandleException( ex, new List { new Param { Name = "lineNumber", Value=lineNumber }, new Param { Name = "text", Value=text }, new Param { Name = "context", Value=context} })) { throw; } } } }
编辑:或者,通过使参数HandleException为params数组:
public static bool HandleException(Exception ex, params Param[] parameters) { ... } ... if (ExceptionHandler.HandleException( ex, new Param { Name = "lineNumber", Value=lineNumber }, new Param { Name = "text", Value=text }, new Param { Name = "context", Value=context} )) { throw; } ...
生成额外的代码以显式地将参数传递给异常处理程序有点痛苦,但是使用加载项至少可以自动化它.
自定义属性可用于注释您不希望加载项传递给异常处理程序的任何参数:
public UserToken RegisterUser( string userId, [NoLog] string password ) { }
2ND编辑:
请注意,我完全忘记了AVICode:
http://www.avicode.com/
他们使用呼叫拦截技术来提供这种信息,因此它必须是可能的.