是否有一种使用DebugFormat()的方法来构造昂贵的args?

时间:2017-11-21 13:10:12

标签: c# log4net

我是log4net和log4j的"format" 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#还是比较陌生的,我不能完全指责它。

1 个答案:

答案 0 :(得分:6)

您可以创建扩展方法或包装类,但要获得令人满意的语法并不容易,因为您需要明确说明某些参数(示例中为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>)))
   );