如何在ErrorWarningLog的AddError/AddWarning方法中自动获取调用类名?
实现自动为错误/警告消息添加调用者类名前缀
完全可以实现这个需求,不用手动在调用时添加类名。通过反射获取调用栈信息,就能在AddError/AddWarning方法内部自动提取调用者的类名并拼接到消息前。
具体实现思路
利用System.Diagnostics.StackTrace和StackFrame获取调用栈的层级信息,定位到调用日志方法的代码所在类,提取类名后与原始消息拼接。
代码示例(C#)
修改后的ErrorWarningLog类
using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; public class ErrorWarningLog { private readonly List<string> _errors = new List<string>(); private readonly List<string> _warnings = new List<string>(); // 禁止方法内联,避免Release模式下栈帧索引错乱 [MethodImpl(MethodImplOptions.NoInlining)] public void AddError(string message) { var callerClassName = GetCallerClassName(); _errors.Add($"{callerClassName} - {message}"); } [MethodImpl(MethodImplOptions.NoInlining)] public void AddWarning(string message) { var callerClassName = GetCallerClassName(); _warnings.Add($"{callerClassName} - {message}"); } private string GetCallerClassName() { // 栈帧索引说明: // 0: 当前GetCallerClassName方法 // 1: 调用它的AddError/AddWarning方法 // 2: 实际触发日志的业务方法(比如Application1.application1_method1) var stackTrace = new StackTrace(); var callerFrame = stackTrace.GetFrame(2); if (callerFrame?.GetMethod().DeclaringType == null) { return "UnknownClass"; } return callerFrame.GetMethod().DeclaringType.Name; } // 对外暴露日志列表的只读副本 public List<string> GetErrors() => new List<string>(_errors); public List<string> GetWarnings() => new List<string>(_warnings); }
业务类调用示例
public class Application1 { public void application1_method1(ErrorWarningLog ewl) { try { // 模拟执行失败逻辑 throw new System.Exception("内部逻辑出错"); } catch { // 无需手动添加类名,方法内部自动处理 ewl.AddError("my error"); } } }
主方法测试
public class Program { public static void Main() { var ewl = new ErrorWarningLog(); var app1 = new Application1(); app1.application1_method1(ewl); // 输出结果:Application1 - my error foreach (var error in ewl.GetErrors()) { System.Console.WriteLine(error); } } }
注意事项
- 性能损耗:创建
StackTrace会有一定性能开销,如果日志方法被高频调用(如每秒上千次),建议在非核心业务路径使用,或考虑缓存调用者信息优化。 - Release模式优化:添加
[MethodImpl(MethodImplOptions.NoInlining)]特性是为了防止编译器在Release模式下内联AddError/AddWarning方法,导致栈帧索引偏移。 - 特殊场景处理:如果在匿名方法、Lambda表达式中调用日志方法,获取到的类名将是包含该Lambda的宿主类,而非业务逻辑类,这种情况需要额外注意。
内容的提问来源于stack exchange,提问作者hdiriaur
相关产品推荐
相关产品推荐

