exception处理中函数参数的通用日志记录

很多我的C#代码遵循这种模式:

void foo(string param1, string param2, string param3) { try { // do something... } catch(Exception ex) { LogError(String.Format("Error in foo(param1={0}, param2={1}, param3={2}), exception={3}", param1, param2, param3, ex.Message)); } } 

有没有办法在.NET中获取函数的键/值列表,以便我可以调用另一个函数来构造我的错误记录字符串? 或者你有更通用/更好的方法吗?

您可以使用Reflection和约定,您必须使用正确的顺序将参数传递给LogError:

 private static void MyMethod(string s, int x, int y) { try { throw new NotImplementedException(); } catch (Exception ex) { LogError(MethodBase.GetCurrentMethod(), ex, s, x, y); } } private static void LogError(MethodBase method, Exception ex, params object[] values) { ParameterInfo[] parms = method.GetParameters(); object[] namevalues = new object[2 * parms.Length]; string msg = "Error in " + method.Name + "("; for (int i = 0, j = 0; i < parms.Length; i++, j += 2) { msg += "{" + j + "}={" + (j + 1) + "}, "; namevalues[j] = parms[i].Name; if (i < values.Length) namevalues[j + 1] = values[i]; } msg += "exception=" + ex.Message + ")"; Console.WriteLine(string.Format(msg, namevalues)); } 

您可以在PostSharp中使用面向方面的编程(请查看http://www.postsharp.org ,以及http://www.codeproject.com/KB/cs/ps-custom-attributes-1.aspx上的教程) )。 基本上你可以这样做:

 public class LogExceptionAttribute : OnExceptionAspect { public override void OnException(MethodExecutionEventArgs eventArgs) { log.error("Exception occurred in method {0}", eventArgs); } } [LoggingOnExceptionAspect] public foo(int number, string word, Person customer) { // ... something here throws an exception } 

也许不是你想要的,但我相信它可以根据你的需要进行调整。

没有办法做到这一点。

通常的做法是不捕获exception,除非你能处理它们。

也就是说,您通常只会捕获exception并将它们记录在顶级exception处理程序中。 然后,您将获得堆栈跟踪,但当然不会获得堆栈中所有方法调用的所有参数的详细信息。

显然,在调试时,您需要尽可能多的细节。 实现这一目标的其他方法是:

  • 使用Debug.Assert语句来测试您正在进行的假设。

  • 使用可以选择性激活的日志记录来检测应用程序。 我使用Log4Net,但也有其他选择,包括使用System.Diagnostics.Trace类。

在任何情况下,如果您只捕获exception以记录它们(我在n层应用程序的层边界执行此操作,以便在服务器上记录exception),那么您应该始终重新抛出它们:

 try { ... } catch(Exception ex) { log(ex); throw; } 

当我这样做时,我刚刚为日志记录创建了一个通用字典。

我有这个LogArgs类。 并登录我遇到exception时调用的基类。

 public class LogArgs { public string MethodName { get; set; } public string ClassName { get; set; } public Dictionary Paramters { get; set; } public LogArgs() { this.Paramters = new Dictionary(); } } 

然后在每个方法的开始我做

 LogArgs args = new LogArgs { ClassName = "ClassName", MethodName = "MethodName" }; args.Paramters.Add("Param1", param1); args.Paramters.Add("Param2", param2); args.Paramters.Add("Param3", param3); base.Logger.MethodStartLog(args); 

当我有错误时,我会这样记录。

 base.Logger.LogError(args, ex); 

您可以使用类似的构造消息的方式,但在LogError方法中添加params关键字来处理参数。 例如:

  public void LogError(string message, params object[] parameters) { if (parameters.Length > 0) LogError(string.Format(message, parameters)); else LogError(message); } 

这是一个过时的post,但万一有人遇到过像我这样的事情 – 我通过使用PostSharp解决了这个问题。

虽然它实际上并不是免费的。 Express许可证(可通过VS中的NuGet下载)允许您使用[Log]属性修饰方法,然后选择已配置的日志记录机制,如log4net nLog等。现在您将开始在日志中看到调试级别条目,提供参数详细信息。

使用快速许可证,我只能在我的项目中装饰最多50个方法。 如果它符合您的需求,您很高兴!

有几个参数或大量参数的场景……

  1. 没有太多麻烦的参数很少,最好将它们作为记录/exception消息的一部分写出来。

  2. 在大型参数中,多层应用程序将使用ENTITIES(如customer,CustomerOrder …)在层之间传输数据。 这些实体应该实现类Object的重写ToString()方法,其中,

Logmessage(“方法启动”+ paramObj.ToString())会给出对象中的数据列表..有什么意见? 🙂

谢谢