我是log4net和log4j 用于记录消息的"格式"API的忠实粉丝,如果没有启用必要的日志级别,这可以避免在参数上调用ToString()的成本.
但是有时候我使用的一个或多个参数不是一个简单的对象,它需要以某种方式构造.例如,像这样:
logger.DebugFormat("Item {0} not found in {1}",
itemID,
string.Join(",", items.Select(i => <you get the idea>))
);
Run Code Online (Sandbox Code Playgroud)
是否有一种封装第二个参数(Join表达式)的技术,除非DebugFormat决定它应该是(就像它对第一个参数的ToString所做的那样),否则它不会被执行?
感觉就像一个lambda或func或者其他东西应该可以在这里提供帮助,但我对C#还是比较新的,我不能完全把手指放在它上面.
您可以创建扩展方法或包装类,但要获得令人满意的语法并不容易,因为您需要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() : "";
}
}
Run Code Online (Sandbox Code Playgroud)
这接受在构造函数中返回对象的函数,并且在调用之前不会调用此函数ToString(),正如您所知,只有在必要时才会调用log4net(如果启用了此类调试级别).然后像这样使用:
logger.DebugFormat("Item {0} not found in {1}",
itemID,
new Delayed(() => string.Join(",", items.Select(i => <you get the idea>)))
);
Run Code Online (Sandbox Code Playgroud)