【发布时间】:2015-11-27 07:43:09
【问题描述】:
此问题与Steven 的答案-here 有关。他提出了一个非常好的记录器包装器。我将他的代码粘贴在下面:
public interface ILogger
{
void Log(LogEntry entry);
}
public static class LoggerExtensions
{
public static void Log(this ILogger logger, string message)
{
logger.Log(new LogEntry(LoggingEventType.Information,
message, null));
}
public static void Log(this ILogger logger, Exception exception)
{
logger.Log(new LogEntry(LoggingEventType.Error,
exception.Message, exception));
}
// More methods here.
}
那么,我的问题是创建代理 log4net 的实现的正确方法是什么?我应该只添加另一个带有类型参数的日志扩展方法,然后在里面创建一个开关吗?在LoggingEventType的情况下使用不同的log4net方法?
第二个问题,在后面的代码中使用它的最佳方式是什么?
因为他写道:
(...) 您可以轻松创建 ILogger 实现 (...) 并配置 您的 DI 容器将其注入到具有 ILogger 的类中 构造函数。
这是否意味着每个将记录某事的类(基本上是每个类)都应该在其构造函数中包含ILogger?
【问题讨论】:
-
“这是否意味着每个类都会记录某事(所以基本上每个)”。如果每个班级都使用记录器,那么您是认真的logging way too much。
-
@Steven 与该答案的赞成票和 cmets 相反,我完全不同意:你永远不能记录太多。特别是对于 Web 服务和 Windows 服务(即后端),面对 UI 的用户几乎没有错误报告,日志记录对于解决问题非常宝贵。当然,您可以说“此代码是 SOLID”,但如果该代码不能通过简单地阅读日志来分析应用程序在崩溃时所做的事情来进行“事后调试”,那么 SOLID 会给您带来什么?当然,有单元测试可以防止出现问题,但代码永远不会完美无缺。
-
@CodeCaster:我在回答中提出的方法实际上是 AOP 的一种形式。如果您在系统中定义了正确的抽象(这就是我的答案),您会发现应用一些为您进行日志记录的装饰器很容易。将此与 Clean Code 混合使用并使用异常快速失败,您会发现像
logger.Log("now we're in this if-branch")和logger.Log("customer is null")这样的调用实际上变得非常罕见。 -
这是一个设计的东西。一组受控的抽象和降低的圈复杂度。所有运行时数据要么是输入参数,要么是从存储(数据库、内存等)中提取的某种形式的有状态数据,所有这些都可以使用方面/装饰器进行记录。当数据在对象图中移动时,拥有数据的详细信息和方法调用的顺序通常足以弄清楚发生了什么,而不会一遍又一遍地用相同的重复代码行污染整个代码@987654329 @。就像我说的,这是一种设计。
-
@TimLaax:使该记录器成为单例/环境上下文,并不会改变它是依赖项的事实;但它确实隐藏了依赖关系。这使得测试、模拟、替换、装饰和拦截变得困难,向任何消费者隐藏这种依赖存在的事实,并且使工具(例如您的 DI 库)无法为您分析对象图。在我的书中,将记录器设为单例绝对不是更好也不是更清洁。使其成为单身人士是对症状的治疗。您在太多类中注入记录器:停止这样做。
标签: c# .net logging log4net nlog