Что является недостатком ручной регистрации экземпляр, такой как log4net регистратор, чтобы выйти из кратера в Autofac?
Autofac имеетмодуль интеграции log4net , называемыйLoggingModule .
Однако, я зарегистрироваться регистратор в выйти из кратера вручную, без использования LoggingModule, и, кажется, работает нормально.
ILog log = LogManager.GetLogger("Logger");
builder.RegisterInstance(log).As<ILog>().SingleInstance();
Мой вопрос - что является недостатком/побочный эффект использования вышеуказанного подхода вместо того, чтобы использовать LoggingModule.
Паутина.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>
Глобальный.асакс.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 ответа:
Единственное различие между этим модулем и пользовательской регистрацией заключается в том, что модуль будет использовать разные экземпляры
LoggingModule
, предоставляемыйAutofac , является усовершенствованным образцом пользовательского модуля.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
, введенной вFoo
иBar
, будет то же самое, и они будут результатомLogManager.GetLogger("Logger")
. Если ты используйтеLoggingModule
log
будет результатомLogManager.GetLogger(typeof(Foo))
дляFoo
иLogManager.GetLogger(typeof(Bar))
дляBar
.Наличие другого экземпляра
ILog
поможет вам фильтровать журнал для определенного типа и тому подобное.Ваша регистрация не имеет проблем, но использование
LoggingModule
позволит вам фильтровать или указывать уровень журнала для некоторого класса или пространства имен.Кстати, я рекомендую вам прочитать исходный код
LoggingModule
, это не очень сложно, и это поможет вам лучше понять, как модуль ипараметр работают сAutofac .
Я бы даже пошел дальше и сказал, что вводить
ILog
непосредственно в ваш код неправильно. Даже еслиILog
является абстракцией, вы все равно нарушите принцип инверсии зависимостей , потому что:В прямом применении инверсии зависимостей, абстракты являются принадлежит верхним / политическим слоям
В то время как в вашем случае абстракция
ILog
принадлежит нижнему уровню (внешней библиотеке журналов).Это плохо, потому что такая абстракция в общее определяется так, как это нравится фреймворку, а не вашему коду. Поэтому он загрязняет ваш код и, кроме того, заставляет ваш код все еще находиться в жесткой зависимости от внешней библиотеки. Это затрудняет последующую замену библиотеки журналов на другую.
Но в случае log4net это становится еще хуже, потому что интерфейс
ILog
является большим нарушением принципа сегрегации интерфейса, потому что он содержит 40 членов. Это делает API намного более сложный, чем требуется, и делает его гораздо труднее имитировать реализацию.Вместо этого было бы гораздо лучше создать абстракцию для ведения журнала, специфичную для приложения (предпочтительно с одним членом, как показано в этом примере ). Когда вы определили абстракцию ведения журнала с одним членом, будет тривиально создать адаптер для log4net, Enterprise Library Logging Application Block, ELMAH или любой другой библиотеки ведения журнала, которую вы можете придумать.
И не забудьте спросить себя:: я записываю слишком много ?