记录框架被注入到类中

时间:2009-08-21 18:35:57

标签: .net logging inversion-of-control

是否应该将日志框架注入需要它们的类中,或者每个需要它的类是否只需要知道框架并直接使用它?我正在使用Log4Net,目前我正在注入一个服务,将该框架包装到需要能够记录的类中,知道日志记录可能不会改变,大多数部分需要它,从这个意义上注入了答案吗? / p>

6 个答案:

答案 0 :(得分:2)

从长远来看,注射更灵活,因为您可以轻松选择性地注入某些位置并有选择地禁用日志记录等。

答案 1 :(得分:1)

我认为注射它并没有错。他们建议仅仅出于性能原因使用静态变量,但我发现这与开始时注入记录器之间没有什么区别。

答案 2 :(得分:1)

如果内存性能不是很大的问题,您可以考虑使用AOP,例如:使用PostSharp。这样你的类根本不需要知道记录器。您基本上将IL-code作为postbuild步骤注入到程序集中。 PostSharp使用属性来标记方法,类甚至整个程序集。对于日志记录问题,甚至有plugin使用log4net。

编辑: 我提到了内存,因为每个属性都为每个连接点创建一个新对象。

答案 3 :(得分:1)

即使你说日志记录不会改变,我建议从特定的日志框架中抽象出来。但是,在所有情况下都不需要注入记录器实例。

CommonLogging为例(参见this Stackoverflow answer以获取Common.Logging的简短描述)例如:您的类直接与工厂(LoggerManager)对话,但您不受特定记录器实现的约束

答案 4 :(得分:0)

如果你正在谈论依赖注入(比如在Spring.NET意义上),那么它并不重要 - 尽管你没有从多个logger实例副本中获得太多价值。通常,具有特定类/名称的框架返回的每个记录器实例无论如何都将是单例,因此问题是您是否希望使用记录器引用来混淆每个实例,而不是每个类的单个静态引用。如果您担心更改记录器实现,请登录到接口(CommonLogging,在另一个答案中提到,执行此操作,并支持log4net和Enterprise Library实现)。

如果你在谈论使用AOP注射,那么我不确定超过某一点,AOP注射更灵活。您几乎只限于使用方法级粒度记录入口,出口和异常。即使您使用AOP选择性地注入代码的一部分,AOP注入也是一种散射方法。虽然伐木被认为是AOP理想的交叉问题,但我从未发现基于AOP的测井在实践中有很大用处(当然是YMMV)。

答案 5 :(得分:0)

CSharpAtl

我很好奇你是如何注入Log4net的?请参阅我的问题/社区维基here

我也看到了你对DI / Log4net问题的回答here

我见过的大多数日志注入示例都显示了一个注入了“logger”的类,如下所示:

public class Foo
{
  private ILogger logger;

  public Foo(ILogger logger) //Injection via constructor
  {
    //Which "named" logger is this anyway?  Is it Foo's?  If so, how is it Foo's?
    this.logger = logger;
  }

  public DoSomeWork(int xyz)
  {
    logger.Info("xyz = {0}", xyz);
  }
}

使用像Log4net(和NLog,以及其他人)这样的东西,你通常会创建一个这样的记录器:

public class Foo
{
  private static ILogger logger = 
          LogManager.GetLogger(
              System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

  public Foo()
  {
  }

  public DoSomeWork(int xyz)
  {
    logger.Info("xyz = {0}", xyz);
  }
}

那么,如果依赖注入,我的班级Foo如何获得正确的记录器?另外,也许我没有严格根据课程命名我的记录器。相反,我可能会根据可能无法从类型派生的功能区域(如“DatabaseAccess”,“AppStartup”,“AppShutdown”等)来命名它们。

您是注入“Logger”(对应于命名的记录器)还是“LogManager”(对应于Log4net的LogManager),或者您正在做其他事情?您是否使用DI平台的配置功能来关联注入依赖项的“命名实例”?我认为Unity支持这样的东西,虽然我不太确定。

以下是我想象注入“LogManager”的方法:

public class Foo
{
  private static ILogger logger;

  public Foo(ILogManager logManager) //Injection via constructor
  {
    logger = logManager.GetLogger
                    (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    //Since logger is (should it be?) static, maybe should be like this:

    if (logger = null)
    {
      logManager.GetLogger
                 (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    }
  }

  public DoSomeWork(int xyz)
  {
    logger.Info("xyz = {0}", xyz);
  }
}

在我看来,注入像ILogManager(其实现将包装Log4net的LogManager)之类的东西比注入ILogger更容易,因为DI平台将如何知道要注入哪个ILogger的问题。

我是DI和.NET日志记录平台的新手(实际上,对于C#和.NET来说一般都是新手)。我过去多年的绝大部分经验是VB6 + VC ++ 6。

感谢您提供任何信息......

开始编辑...

我已经了解了更多,并且发现你也问过AutoFac,所以我猜你正在使用它来做你的DI。如果这是真的,那么我猜你也在做类似this的事情,或者显然更好,比如this来解决你的记录器(按类类型)。我想这回答了至少在AutoFac中如何注入命名记录器(例如来自Log4Net或NLog)的问题。

结束编辑...