异常处理中功能参数的通用记录

时间:2020-03-06 14:44:49  来源:igfitidea点击:

我的很多Ccode都遵循这种模式:

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中是否有一种方法可以获取函数的参数的键/值列表,以便我可以调用另一个函数来构造错误日志记录字符串?
或者
我们是否有更通用/更好的方法来做到这一点?

解决方案

完成此操作后,我刚刚创建了用于日志记录的通用字典。

我有这个LogArgs类。并登录有异常时调用的基类。

public class LogArgs
{

    public string MethodName { get; set; }
    public string ClassName { get; set; }
    public Dictionary<string, object> Paramters { get; set; }

    public LogArgs()
    {
        this.Paramters = new Dictionary<string, object>();
    }

}

然后在我做每一种方法的开始

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);

没有,没有办法做到这一点。

通常的做法是不捕获异常,除非我们可以处理它们。

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

显然,在调试时,我们需要尽可能多的细节。实现此目的的其他方法是:

  • 自由地使用Debug.Assert语句来测试我们所做的假设。
  • 使用可选择性激活的日志记录对应用程序进行检测。我使用Log4Net,但还有其他替代方法,包括使用System.Diagnostics.Trace类。

无论如何,如果我们确实捕获异常只是为了记录它们(我将在n层应用程序的层边界中执行此操作,以便将异常记录在服务器上),那么我们应该始终重新抛出它们:

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

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

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

我们可以使用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
}

也许不是我们想要的,但是我敢肯定它可以进行调整以满足需求。