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

Guy*_*Guy 27 .net c#

我的很多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));
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Pan*_*nos 32

您可以使用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));
}
Run Code Online (Sandbox Code Playgroud)


Jac*_*cob 7

您可以在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
}
Run Code Online (Sandbox Code Playgroud)

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


Joe*_*Joe 5

没有办法做到这一点.

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

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

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

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

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

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

try
{
    ...
}
catch(Exception ex)
{
    log(ex);
    throw;
}
Run Code Online (Sandbox Code Playgroud)