异常处理中功能参数的通用记录
时间: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 }
也许不是我们想要的,但是我敢肯定它可以进行调整以满足需求。