是否有一种技术可以将 DebugFormat() 与构建成本高昂的参数一起使用?

问题描述 投票:0回答:2

我是 log4net 和 log4j 用于记录消息的“格式”API 的忠实粉丝,这可以避免在未启用必要的日志级别时对参数调用 ToString() 的成本。

但有时我使用的一个或多个参数不是一个简单的对象,它需要以某种方式构造。例如,像这样:

logger.DebugFormat("Item {0} not found in {1}",
        itemID,
        string.Join(",", items.Select(i => <you get the idea>))
       );

是否有一种技术可以封装第二个参数(Join 表达式),以便除非 DebugFormat 决定它应该执行(就像对第一个参数的 ToString 所做的那样),否则它不会被执行?

感觉 lambda 或 func 或其他东西应该能够在这里提供帮助,但我对 C# 相当陌生,我不太清楚它。

c# log4net
2个回答
7
投票

您可以创建扩展方法或包装类,但获得令人满意的语法并不容易,因为您希望明确声明一些参数(示例中的

itemID
),并且仅在必要时才解析一些参数。但是你不能将匿名函数作为
object
传递。相反,我会使用另一个不需要扩展方法或包装器的解决方案。像这样创建类:

public sealed class Delayed {
    private readonly Lazy<object> _lazy;
    public Delayed(Func<object> func) {
        _lazy = new Lazy<object>(func, false);
    }

    public override string ToString() {
        var result = _lazy.Value;
        return result != null ? result.ToString() : "";
    }
}

此函数接受在构造函数中返回对象的函数,并且在调用

ToString()
之前不会调用此函数,正如您所知,log4net 仅在必要时才会调用该函数(如果启用了此类调试级别)。然后像这样使用:

logger.DebugFormat("Item {0} not found in {1}",
    itemID,
    new Delayed(() => string.Join(",", items.Select(i => <you get the idea>)))
   );

0
投票

我猜 log4net 设计此用例的方式是提出 Is{Level}Available() 方法,例如 IsDebugEnabled() 方法,仅当接收者记录器的级别实际上处于活动状态时,该方法才返回 True。 因此,您可以使用昂贵构造的参数保留您的 LogFormat() 调用,但只需将其括起来:

if (logger.IsDebugEnabled())
    {
    ...
    }
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.