Подтвердить что ты не робот

Как использовать log4net с Injection Dependency

Я пытаюсь выяснить, что такое правильное использование и использование log4net с инфраструктурой инъекций зависимостей.

Log4Net использует интерфейс ILog, но мне требуется позвонить

LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType)

в каждом классе или методе, где мне нужно записывать информацию. Это, похоже, противоречит принципам IoC и связывает меня с использованием 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);
    }
}
4b9b3361

Ответ 1

Я думаю, вы не видите лес для деревьев здесь. ILog и LogManager - это легкий фасад, эквивалентный почти 1:1, эквивалентный публичному протоколу Apache и фактически не соединяющий ваш код с остальной частью log4net.

<rant>
Я также обнаружил, что почти всегда, когда кто-то создает оболочку MyCompanyLogger вокруг log4net, они пропускают эту проблему плохо и либо потеряют важные и полезные возможности структуры, отбрасывают полезную информацию, теряют прирост производительности, используя даже упрощенный интерфейс ILog, или все, что выше. Другими словами, упаковка log4net, чтобы избежать связи с ней, является анти-шаблоном.
</rant>

Если вы почувствуете необходимость его вставить, сделайте свой экземпляр журнала доступным через свойство, чтобы включить инъекцию, но создайте экземпляр по умолчанию старомодным способом.

Что касается включения контекстного состояния в каждое сообщение журнала, вам нужно добавить глобальное свойство, чья ToString() разрешает то, что вы ищете. В качестве примера, для текущего размера кучи:

public class TotalMemoryProperty
{
    public override string ToString()
    {
        return GC.GetTotalMemory(false).ToString();
    }
}

Затем подключите его во время запуска:

GlobalContext.Properties["TotalMemory"] = new TotalMemoryProperty();

Ответ 2

Как я это сделал, это создать свой собственный интерфейс и реализовать класс, который использовал интерфейс Log4Net, и ввел этот класс. Таким образом, вы не привязаны к Log4Net... вы можете просто создать другой класс для нового регистратора и ввести этот класс.

Ответ 3

Если вы действительно обеспокоены наличием нескольких регистраторов, вы всегда можете объявить глобальный регистратор и вызвать его для всех ваших нужд ведения журнала. Недостатком этого является то, что вы теряете встроенную способность идентифицировать класс, из которого был выпущен журнал, но вы также можете ввести свое собственное сообщение в журнал, чтобы идентифицировать класс.

Это зависит от того, насколько вы надежны для ведения журнала. Вы также можете просто поставить логгер в основной класс и позволить всем необработанным исключениям пузыриться до него для ведения журнала.

Ответ 4

Еще один способ сделать это - подключить регистрационную последовательность контейнера интерфейса logognet log4net следующим образом: (например, используя замок в контексте ASP.NET ниже)

container.Register(Component.For<ILog>().LifeStyle
    .PerWebRequest.UsingFactoryMethod(() => LogManager.GetLogger(
    MethodBase.GetCurrentMethod().DeclaringType)));

и просто конструктор-вставляйте ILog всякий раз, когда вам это нужно.