【问题标题】:C# derived class type needed in base for logging using NLog使用 NLog 进行日志记录所需的 C# 派生类类型
【发布时间】:2012-01-03 11:07:26
【问题描述】:

我们使用 NLog 来登录 C# MVC3 Web 应用程序。我们所有的控制器都扩展了一个自定义基础“ApplicationController”,让我们可以访问经常需要的方法和成员。

我希望所有控制器都可以通过此基类访问 Logger,但希望了解日志语句源自哪个派生类的详细信息。

我们的应用程序控制器如下所示:

public abstract class ApplicationController : Controller
{
    protected Logger _logger;
    protected virtual Logger Logger
    {
        get { return _logger ?? (_logger = LogManager.GetCurrentClassLogger()); }
    }

    protected ApplicationController()
    {
        Context = new Entities();
    }

如果派生控制器未覆盖 Logger,则所有语句都将显示它们源自应用程序控制器。目前,我在所有派生控制器中都有基本相同的 Logger 语句。例如:

public class PropertyController : ApplicationController
{
    private readonly DatatapeService _datatapeService;
    private readonly PropertyService _propertyService;
    protected override Logger Logger
    {
        get { return _logger ?? (_logger = LogManager.GetCurrentClassLogger()); }
    }

显然这是一种糟糕的实施实践。

  1. 我怎样才能把它弄干?具体来说,我对C#的理解是什么 缺乏完成这个特定的任务?
  2. 在不暴露 直接记录类 (NLog)?

TIA!

【问题讨论】:

    标签: c# inheritance nlog


    【解决方案1】:

    我不熟悉 NLog 但在 Log4Net 中的语法 LogManager.GetLogger(this.GetType()) 将完成您想要的。 GetType返回继承层次结构中的叶类型,即使在基类 ApplicationController 中调用,当第一次创建记录器时(即:第一次访问 Logger 属性时)它将使用类型 PropertyController 实例化它/p>

    【讨论】:

    • 我认为this.GetType().Name 应该这样做。
    • 这正是我所采用的。我没有意识到 this.GetType 会返回最派生的类。这允许我在我的 ApplicationController 上创建一个属性,然后在整个应用程序中使用该记录器。
    • 更新 07/2017:他们 (NLog) 现在在他们的教程中解决了这个问题。见:github.com/NLog/NLog/wiki/Tutorial#expose-logger-to-sub-classes
    【解决方案2】:

    NLog API 与 Log4net 略有不同。你需要使用

    Logger = LogManager.GetLogger(GetType().Name);
    

    如果您只传递类型,LogManager 将需要一个记录器类型(即自定义记录器)

    【讨论】:

    • 我觉得 LogManager.GetLogger(GetType().FullName) 更有用
    • 谢谢@DavidHayes——同意你的看法。因此,对于基类属性,等效于 GetCurrentClassLogger() 将使用:get { return _logger ?? (_logger = LogManager.GetLogger(this.GetType().FullName)); }
    【解决方案3】:

    NLog wikiHow to create Logger for sub classes 页面现在建议以下模式:

    class BaseClass
    {
        protected BaseClass()
        {
            Log = LogManager.GetLogger(GetType().ToString());
        }
    
        protected Logger Log { get; private set; }
    }
    
    class ExactClass : BaseClass
    {
        public ExactClass() : base() { }
        ...
    }
    

    【讨论】:

      【解决方案4】:

      只需检查 nLog wiki here

      在大多数情况下,每个班级都有一个记录器,因此 给 logger 赋予与当前类相同的名称是有意义的。

      这样做很有意义

      public abstract class ApplicationController : Controller
      {
          protected Logger _logger;
          protected virtual Logger Logger(string className)
          {
             return LogManager.GetLogger(className);
          }
      }
      
      
      public class PropertyController : ApplicationController
      {
          private readonly DatatapeService _datatapeService;
          private readonly PropertyService _propertyService;
          protected override Logger Logger()
          {
              return base.Logger("PropertyController ");
          }
      }
      

      【讨论】:

      • 我真的不喜欢这种方法。如果我这样做,我将在每个控制器中复制和粘贴代码。有这么多重复感觉不对。
      • @BobbyB sn-p,通用基类? NLog 为记录器配置使用享元模式,因此开销最小。实际记录的行在很大程度上是重复的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      • 1970-01-01
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多