在基类中定义的log4net记录器

10 浏览
0 Comments

在基类中定义的log4net记录器

我想在我的MVC控制器抽象基类中构建我的log4net记录器,如下所示:

protected static readonly ILog Log = LogManager.GetLogger(typeof(AuthorizedController));

这样我只需定义一次记录器即可。唯一的问题是,日志输出中的记录器属性将始终是AuthorizedController,如果我有FooController继承自AuthorizedController,我希望日志输出能反映这一点。

有什么简洁、干净、高效的方法可以做到这一点?

0
0 Comments

在这段代码中,我们可以看到一个log4net logger的定义,它被定义在一个基类中。这个logger是通过调用LogManager.GetLogger方法来创建的。然而,这种方式在实例化不同类型的对象时可能会导致问题。

问题的根源是,基类中的logger是通过调用GetType方法来创建的。这意味着无论我们实例化的是基类还是派生类,都会得到相同的logger实例。这可能会导致日志信息在不同类型的对象之间进行共享,从而造成混乱和错误的日志记录。

为了解决这个问题,我们可以使用Steve Guidi提供的方法,通过GetType方法为特定类型的实例创建logger。具体做法是,在基类中定义一个私有字段_log,并将其作为logger实例的引用。在基类的属性Log中,我们使用null合并运算符来检查_log字段是否为空,如果为空,则通过LogManager.GetLogger(GetType())来创建logger实例,并将其赋值给_log字段。这样,每个实例都会有自己的logger实例。

下面是修改后的代码示例:

private ILog _log;

protected ILog Log => _log ?? (_log = LogManager.GetLogger(GetType()));

通过这种方式,我们可以确保每个实例都有自己独立的logger实例,避免了日志信息共享的问题,从而提高了日志的准确性和可读性。

0
0 Comments

log4net日志记录器定义在基类中的问题是,每次需要访问日志记录器时,都需要进行多个方法调用,这可能导致性能下降。为了解决这个问题,可以将日志记录器定义为一个属性,每个派生类在构造函数中调用此属性并保存日志记录器的副本。

在log4net系统中,调用LogManager.GetLogger()方法可以获取到一个日志记录器实例。根据经验判断,log4net系统可能使用了一些缓存和延迟初始化的技术,以便快速检索已请求的实例。因此,使用相同的类型参数两次调用LogManager.GetLogger()方法应该返回同一个实例。

为了解决日志记录器访问的性能问题,可以将字段替换为以下属性:

protected ILog Logger
{
    get { return LogManager.GetLogger(GetType()); }
}

此属性使用GetType()方法获取当前类型,并调用LogManager.GetLogger()方法获取日志记录器实例。

另外,log4net从Hashtable中读取以解析日志记录器。虽然O(1)的时间复杂度并不算太高,但每次访问日志记录器时都需要进行多个方法调用可能会降低性能。因此,一个更好的解决方法是让每个派生类在其构造函数中调用上述属性,并保存日志记录器的副本。

至于“常数时间‘不太糟糕’”的问题,可能是指O(1)的时间复杂度相对较低,但代码中会有更多的样板代码。但从功能上来说,并没有什么区别。

通过将日志记录器定义为属性,并在每个派生类的构造函数中调用该属性并保存副本,可以提高日志记录器的访问性能。这种方法可以避免每次访问日志记录器时都进行多个方法调用,从而提高代码的执行效率。

0
0 Comments

在这段内容中,作者提到了使用NInject作为一个IoC容器,并且给出了一个使用ILog的示例。作者在请求类型的构造函数中注入ILog,但是与其绑定到一个实例不同,作者将其绑定到一个提供者。作者使用了一个名为MyProvider的提供者,并在Create方法中返回了一个由LogManager获取的logger。这样每个类型都会接收到一个与在构造函数中使用GetLogger(GetType())相同的logger。

问题的出现原因是在基类中定义了log4net logger。这会导致每次在派生类中使用GetLogger(GetType())时,都会返回基类的logger,而不是派生类的logger。

解决方法是在派生类中重新定义logger。可以在派生类的构造函数中使用GetLogger(GetType())重新定义logger,以确保每个派生类都有自己的logger。

0