Log4net logger, определенный в базовом классе
Я хочу построить свой логгер log4net в моем базовом классе контроллера MVC следующим образом:
protected static readonly ILog Log = LogManager.GetLogger(typeof(AuthorizedController));
Таким образом, я могу определить регистратор один раз и сделать с ним. Единственная проблема заключается в том, что атрибут logger в выходном файле журнала всегда будет AuthorizedController
, и если у меня есть FooController
, унаследованный от AuthorizedController
, я бы хотел, чтобы вывод журнала отражал это.
Что было бы хорошим KISS, DRY и эффективным способом сделать это?
Ответы
Ответ 1
Я не уверен, насколько дорогой вызов LogManager.GetLogger()
, но я подозреваю, что в системе log4net есть некоторая умная кэширование и/или ленивая инициализация, которая позволяет запрашивать экземпляры для быстрого извлечения. В конце концов, нет причин, по которым вызов LogManager.GetLogger()
дважды с тем же параметром типа возвращал бы другой экземпляр.
Тем не менее, возможно, заменяя поле следующим свойством.
protected ILog Logger
{
get { return LogManager.GetLogger(GetType()); }
}
GetType()
является виртуальным и перегруженным, поэтому каждый конкретный тип будет предоставлять свой тип при вызове этого свойства.
Ответ 2
Я сделал что-то подобное, используя NInject в качестве контейнера IoC, но, полагаю, вы можете воспользоваться идеей для использования с вашим собственным контейнером,
В основном я вставляю ILog в конструктор запрашивающих типов, но вместо привязки к экземпляру привязываю его к провайдеру.
kernel.Bind<ILog>().ToProvider<MyProvider>();
public object Create(IContext context)
{
return LogManager.GetLogger(context.Request.Target.Member.DeclaringType);
}
чтобы каждый тип получал регистратор, который является тем же самым, что и GetLogger(GetType())
в конструкторе.
Ответ 3
Наличие статического регистратора (или статических экземпляров в целом) является плохой практикой. Это может легко привести к нежелательной связи между несвязанными компонентами.
Вам следует рассмотреть возможность добавления в игру зависимости Injection/Inverse of Control. Попросите регистратора ввести в ctor класса. Большинство фреймворков позволяет вам определять разные реализации в разных контекстах.
Мы используем Castle Windsor в наших продуктах
Вы также можете посмотреть этот пост, чтобы найти пример использования ведения журнала вместе с DI
Ответ 4
Как предложил Стив Гуиди - используйте GetType для создания регистратора для конкретного экземпляра типа. Вы можете сохранить ссылку на экземпляр регистратора, который вызывает вызов LogManager.GetLogger в поле поддержки:
private ILog _log;
protected ILog Log => _log ?? (_log = LogManager.GetLogger(GetType()));