微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

依赖注入 – 将NLog与MEF一起使用的最佳方法是什么?

我想知道将NLog与托管可扩展性框架(MEF)一起使用的最佳方法是什么?

我有一个使用MEF架构支持插件的应用程序(导入和导出等)
我想为我的应用程序添加日志记录功能.
作为日志记录组件,我想使用NLog.

你会推荐什么?
1.为NLog创建一个包装器,即配置NLog的其他插件,并导出其他插件导入的函数,如void Log(字符串级别,字符串消息)
2.每个插件都应该拥有自己配置和使用的NLog实例. (他们都会写到同一个文件).

这是一个有趣的方法,但是,它似乎有一个缺点,即注入的所有记录器(或注入的一个单独的)将是相同的实例(或将具有相同的名称,名称是NLogLoggingService类.这意味着你不能很容易地控制日志记录的粒度(即在一个类中将日志记录转换为“Info”级别,在另一个类中转换为“Warn”).另外,如果您选择使用调用站点格式化标记,那么将始终将呼叫的呼叫站点作为NLog记录器,而不是应用程序代码中的呼叫站点.

以下是链接的记录器的缩写版本:

[Export(Services.Logging.LoggingService,typeof(ILoggingService))] 
  class NLogLoggingService : ILoggingService 
  { 
    Logger log; public NLogLoggingService() 
    { 
      log = LogManager.GetCurrentClassLogger(); 
    } 

    public void Debug(object message) 
    {
      log.Debug(message); 
    }
    public void DebugWithFormat(string format,params object[] args) 
    { 
      if (args.Length == 0) 
      { 
        log.Debug(format); 
      } 
      else
      { 
        Debug(string.Format(format,args)); 
      }
    } 
    public bool IsDebugEnabled 
    { 
      get 
      { 
        return log.IsDebugEnabled; 
      } 
    } 
  }

在构造函数中,LogManager.GetCurrentClassLogger()用于获取NLog记录器. GetCurrentClassLogger将返回一个基于“当前”类型“命名”的NLog记录器,在这种情况下,它是NLogLoggingService.因此,要在app.config文件中配置NLog,您将根据记录器名为“SoapBox.Core.NLogLoggingService”进行配置.通常,在直接使用NLog(或log4net)的代码中,每个类都有自己的唯一命名记录器,如下所示:

namespace MyNamespace
{
  public class MyClass1
  {
    private static readonly Logger logger LogManager.GetCurrentClassLogger();

    public void DoSomeWork()
    {
      logger.Info("Logging from inside MyClass1.DoSomeWork");
    }
  }

  public class MyClass2
  {
    private static readonly Logger logger LogManager.GetCurrentClassLogger();

    public void DoSomeWork()
    {
      logger.Info("Logging from inside MyClass2.DoSomeWork");
    }
  }
}

现在,MyClass1和MyClass2的日志记录是可单独控制的.您可以为每个类配置不同的级别,将它们发送到不同的目标,或者完全关闭一个或两个级别.或者,由于log4net和NLog中记录器层次结构的概念,您可以通过为命名空间(本例中为MyNamespace)或任何“祖先”命名空间配置“记录器”来同时控制两个类中的记录.如果没有为完全限定的类型名配置记录器,则日志记录框架实质上是通过将名称设置为点分隔字符串并删除最后一个块并检查该记录器是否已配置来向上移动层次结构.因此,我们要求MyNamespace.MyClass1和MyNamespace.MyClass2的记录器.我可以配置app.config文件让MyNamespace登录“info”并写入文件目标(log4net-speak中的appender).如果我这样做,那么我通过其完全限定名称请求的两个记录器都将继承MyNamespace配置.

使用建议的通过MEF注入NLog的方法,您将只有一个记录器实例,因此您无法将每个类配置为以不同方式记录.此外,正如我之前提到的,如果您选择记录调用站点信息,您将始终获得该类的“SoapBox.Core.NLogLoggingService”和该方法的“Debug”(或DebugWithFormat,或Info或InfoWithFormat等).

这似乎是从log4net和NLog成功注入记录器的问题.几个月前你可以看到我问过这个问题的question.

最后,我能够弄清楚一些依赖注入框架如何成功注入特定于正在创建的类的log4net和NLog记录器(即,如果DI框架实例化MyClass,而MyClass又依赖于ILogger接口,那么MyClass将获得一个记录器,它基本上等同于MyClass通过LogManager.GetCurrentClassLogger api请求记录器本身时发生的记录.通常,DI / IoC框架中的“解析器”被赋予当前上下文(包含当前正在创建的对象的类型等信息).在该类型可用的情况下,让日志框架特定的解析器接收该类型并将其传递给日志框架以创建适合该类型的记录器变得简单.

为了充分利用NLog(和log4net)的功能,你真的希望能告诉MEF你的类依赖于“ILogger”,而且注入你的类的“ILogger”实例应该取决于你班级的类型.

我不知道用MEF实现这一目标是多么容易.或者,您可以将NLog的静态LogManager包装在ILogManager中并注入它.这将偏离正常的“注入ILogger”范式.

总结一下:如果以这种方式通过MEF注入NLog,您确实可以使用NLog进行日志记录,但是您只能拥有一个命名的记录器(SoapBox.Core.NLogLoggingService).这意味着您将无法控制任何粒度 – 无论是级别/开/关还是输出(NLog Target / log4net Appender)

就通过MEF注入NLog并保持“原始”NLog为您提供的粒度/灵活性而言,我没有一个好的答案.

我可以说我们已经决定使用Common.Logging for .NET来抽象日志框架,但我们决定不注入日志记录.相反,我们将使用静态LogManager(由Common.Logging提供)来分发记录器.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐