删除 PostSharp 日志消息中的前缀

Delete prefix in PostSharp log message

我使用 PostSharp LogAttribute 和 log4net 为调用的所有方法生成跟踪。

输出很好,但我想去掉每行的重复标签 Entering:

17:48:34,694 [Main      ]       Entering: LoginPopUp.LoginClick() 
17:48:34,695 [Main      ]         Entering: UserRepository.GetUser() 
17:48:34,695 [Main      ]           Entering: UserRepository.IsAdmin() 
17:48:34,696 [Main      ]             Entering: SecurityManager.Encrypt() 

this answer 可以明显看出 PostSharp 团队不会添加消息格式自定义。

还有一个自定义的例子TraceAttribute derived from OnMethodBoundaryAspect 而且定制起来似乎更灵活。但问题是,在这种情况下,我丢失了显示嵌套级别的缩进(对我来说,这比在每一行都输入 Entering 单词更重要)。

最好的解决方案是扩展 LogAttribute 以自定义前缀,但我不知道是否可行。

那么如何删除 Entering: 前缀?

基于 Peter 答案的工作代码

    static readonly Dictionary<Thread, int> DepthDictionary = new Dictionary<Thread, int>();

    // Invoked at runtime before that target method is invoked.
    public override void OnEntry(MethodExecutionArgs args)
    {
        int depth;
        DepthDictionary.TryGetValue(Thread.CurrentThread, out depth);
        Trace.WriteLine(getIndent(depth) + this.enteringMessage, this.category);
        DepthDictionary[Thread.CurrentThread] = depth+1;
    }

    // Invoked at runtime after the target method is invoked (in a finally block).
    public override void OnExit(MethodExecutionArgs args)
    {
        var depth = --DepthDictionary[Thread.CurrentThread];
        Trace.WriteLine(getIndent(depth) + this.exitingMessage, this.category);
    }

    private string getIndent(int depth)
    {
        string result = "";
        for (int i = 0; i < depth; i++) result += "    ";
        return result;
    }

可以在 log4net 自定义 PatternLayoutConverter 中使用 string.Replace 删除它,但这似乎不是最佳解决方案。

如果能有一个基于自定义 TraceAttribute 的解决方案就好了。

如果您的解决方案不是多线程的,您可以自己添加缩进:

    // Invoked only once at runtime from the static constructor of type declaring the target method.
    public override void RuntimeInitialize(MethodBase method)
    {
        string methodName = method.DeclaringType.FullName + method.Name;
        this.enteringMessage = methodName;
        this.exitingMessage = methodName;
    }

    static int depth = 0; 

    // Invoked at runtime before that target method is invoked.
    public override void OnEntry(MethodExecutionArgs args)
    {
        Trace.WriteLine(getIndent()+this.enteringMessage, this.category);
        depth++;
    }

    // Invoked at runtime after the target method is invoked (in a finally block).
    public override void OnExit(MethodExecutionArgs args)
    {
        depth--;
        Trace.WriteLine(getIndent()+this.exitingMessage, this.category);
    }

    private string getIndent(){
        string result = "";
        for (int i = 0; i < depth;i++) result += "    ";
        return result;
    }

example-trace