You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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);
        }
    }
}

注意事项

  1. 性能损耗:创建StackTrace会有一定性能开销,如果日志方法被高频调用(如每秒上千次),建议在非核心业务路径使用,或考虑缓存调用者信息优化。
  2. Release模式优化:添加[MethodImpl(MethodImplOptions.NoInlining)]特性是为了防止编译器在Release模式下内联AddError/AddWarning方法,导致栈帧索引偏移。
  3. 特殊场景处理:如果在匿名方法、Lambda表达式中调用日志方法,获取到的类名将是包含该Lambda的宿主类,而非业务逻辑类,这种情况需要额外注意。

内容的提问来源于stack exchange,提问作者hdiriaur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:32:24