在Autofac中手动将Log4Net Logger实例注册到ILog有什么缺点?

时间:2015-05-05 15:05:31

标签: c# asp.net log4net autofac

Autofac已log4net Integration Module名为 LoggingModule

但是,我在不使用 LoggingModule 的情况下手动将 Logger 注册到 ILog ,它似乎正常工作。

ILog log = LogManager.GetLogger("Logger");
builder.RegisterInstance(log).As<ILog>().SingleInstance();

我的问题是 - 使用上述方法而不是使用 LoggingModule 的缺点/副作用是什么。

的web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="mylogfile.txt" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="5" />
      <maximumFileSize value="10MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
      </layout>
    </appender>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="RollingFileAppender" />
    </root>
  </log4net>
</configuration>

的Global.asax.cs

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

namespace DemoLog4NetAuftofac
{
    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            var builder = new ContainerBuilder();

            builder.RegisterControllers(typeof(MvcApplication).Assembly);

            ILog log = LogManager.GetLogger("Logger");
            builder.RegisterInstance(log).As<ILog>().SingleInstance();

            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

的HomeController

namespace DemoLog4NetAuftofac.Controllers
{
    public class HomeController : Controller
    {
        public HomeController(ILog log)
        {
            log.Debug("Debug application");
            log.Error("Error application");
            log.Info("Info application");
        }
    }
}

  <package id="Autofac" version="3.4.0" targetFramework="net45" />
  <package id="Autofac.Mvc5" version="3.3.4" targetFramework="net45" />
  <package id="log4net" version="2.0.3" targetFramework="net45" />

2 个答案:

答案 0 :(得分:3)

Autofac 提供的LoggingModule是自定义模块的高级示例。

此模块与自定义注册之间的唯一区别是模块将为注入它的每种类型使用不同的ILog实例,而在代码中,您将只使用ILog的一个实例。

例如:

public class Foo
{
    public Foo(ILog log)
    { 
        Console.WriteLine(log.Logger.Name);
    }
}
public class Bar
{
    public Bar(ILog log)
    { 
        Console.WriteLine(log.Logger.Name);
    }
}

将自定义注册log注入FooBar将是相同的,它们将是LogManager.GetLogger("Logger")的结果。如果您使用LoggingModule log,则LogManager.GetLogger(typeof(Foo))的{​​{1}}和Foo的{​​{1}}会产生LogManager.GetLogger(typeof(Bar))的结果。

拥有Bar的不同实例将帮助您过滤特定类型和类似事件的日志。

您的注册没有问题,但使用ILog将允许您过滤或指定某个类或命名空间的日志级别。

顺便说一句,我建议您阅读LoggingModule源代码,这并不困难,它将帮助您更好地理解模块参数使用 Autofac

答案 1 :(得分:3)

我甚至会说,直接在代码中注入ILog是错误的。即使ILog是抽象,您仍然会违反Dependency Inversion Principle,因为:

  

在直接应用依赖倒置时,摘要是   由上层/政策层拥有

在您的情况下,ILog抽象由较低层(外部日志库)拥有。

这很糟糕,因为这种抽象通常以一种令人满意的方式定义 - 而不是你的代码。因此,它会污染您的代码,除此之外,它还会使您的代码依赖于外部库。这使得以后更换日志库变得更加困难。

但是在log4net的情况下,它变得更糟,因为ILog界面是一个很大的Interface Segregation Principle违规,因为它包含 40个成员。这使得API比所需的复杂得多,并且使得模拟实现变得更加困难。

相反,您可以更好地为日志记录创建特定于应用程序的抽象(最好有一个成员为this example节目)。当您使用一个成员定义日志记录抽象时,为log4net,Enterprise Library Logging Application Block,ELMAH或您能想到的任何其他日志库创建适配器将是微不足道的。

别忘了问问自己:Do I log too much