Как использовать log4net с инъекцией зависимостей
Я пытаюсь выяснить, что такое правильная скороговорка и использование log4net с каркасом инъекции зависимостей.
Log4Net использует интерфейс ILog, но требует, чтобы я позвонил
LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType)
в каждом классе или методе, где мне нужно войти информация. Это, кажется, идет вразрез с принципами МОК и связывает меня с использованием Log4Net.
Я должен как-то положить в другой слой абстракции где-то?
кроме того, мне нужно войти пользовательские свойства, как текущее имя пользователя выглядит так:
log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
как я могу инкапсулировать это так, что мне не нужно помнить, чтобы делать это каждый раз и по-прежнему поддерживать текущий метод, который ведет журнал. должен ли я сделать что-то подобное или я полностью пропустил отметку?
public static class Logger
{
public static void LogException(Type declaringType, string message, Exception ex)
{
log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
ILog log = LogManager.GetLogger(declaringType);
log.Error(message, ex);
}
}
4 ответа:
Я думаю, что вы не видите леса за деревьями здесь. ILog и LogManager-это легкий фасад почти 1: 1, эквивалентный Apache commons-logging, и фактически не связывает ваш код с остальной частью log4net.
<rant>
Я также обнаружил, что почти всегда когда кто-то создает обертку MyCompanyLogger вокруг log4net, они плохо пропускают точку и либо теряют важные и полезные возможности фреймворка, выбрасывают полезные информация, потерять прирост производительности возможно, используя даже упрощенный интерфейс ILog, или все вышеперечисленное. Другими словами,обертывание log4net, чтобы избежать соединения с ним, является анти-шаблоном.</rant>
если вы чувствуете необходимость ввести его, сделайте свой экземпляр logger доступным через свойство, чтобы включить инъекцию, но создать экземпляр по умолчанию старомодным способом.
Что касается включения контекстного состояния в каждое сообщение журнала, вам нужно добавить глобальный чья собственность
ToString()
решает то, что вы ищете. Например, для текущего размера кучи:public class TotalMemoryProperty { public override string ToString() { return GC.GetTotalMemory(false).ToString(); } }
затем подключить его во время запуска:
GlobalContext.Properties["TotalMemory"] = new TotalMemoryProperty();
Как я это сделал, чтобы создать свой собственный интерфейс, и имел класс реализовать этот интерфейс, который использовал Log4Net, и ввел этот класс. Таким образом, вы не привязаны к Log4Net...вы можете просто создать другой класс для нового регистратора и ввести этот класс.
Если вы действительно обеспокоены наличием нескольких регистраторов, вы всегда можете объявить глобальный регистратор и вызвать его для всех ваших потребностей в журналировании. Недостатком этого является то, что вы теряете встроенную способность идентифицировать класс, из которого был выпущен журнал, но вы также можете ввести свое собственное пользовательское сообщение в журнал для идентификации класса.
Это зависит от того, насколько надежным вы хотите, чтобы ведение журнала было. Вы также можете просто поставить регистратор в основной класс и пусть все необработанные исключения пузырь до него для ведения журнала.
другой способ сделать это - подключить последовательность регистрации контейнера интерфейса log4net ILog следующим образом: (используя замок в ASP.NET контекст ниже в качестве примера)
container.Register(Component.For<ILog>().LifeStyle .PerWebRequest.UsingFactoryMethod(() => LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType)));
и просто конструктор-inject ILog всякий раз, когда вам это нужно.