Интерфейсы ввода и регистрации

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

Инъекция зависимостей, как представляется, указывает, что внешние зависимости должны быть введены извне (конструкторы или конструкторы свойств), поэтому следует взять экземпляр ILog в конструкторе и использовать его в классе? Должен ли я рассмотреть возможность регистрации дополнительной зависимости и получить ее в сеттер? Я нажимаю на слишком большую гибкость, позволяя изменить интерфейс ведения журнала, и должен ли я просто зависеть от конкретного интерфейса ведения журнала (например, создать статическую переменную ILog посредством вызова метода factory)? Может ли этот метод factory вызывать в контейнер, чтобы получить реализацию ILog, или это создаст конфликты инициализации инициализации статических переменных и инициализируется контейнер IoC?

Должен ли я делать это:

public class MyService : ISomeService
{
  private static readonly ILogger s_log = 
            LoggingFactory.GetLogger(typeof(MyService))
  ...
}

или, возможно, это:

public class MyService : ISomeService
{
  protected virtual ILogger Logger {get; private set;}
  public MyService(ILogger logger, [other dependencies])
  {
    Logger = logger;
  }
}

или даже это:

public class MyService : ISomeService
{
  public virtual ILogger Logger {get; set;}
  public MyService()
  {
  }
}

Другие шаблоны или способы сделать это? Что там делают люди? Что работает и когда?

Ответ 1

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

Но для вашего вопроса есть еще одна концепция, которую вы, возможно, захотите изучить: аспектно-ориентированное программирование.

В .NET существуют некоторые хорошие рамки для выполнения аспектно-ориентированного программирования, в том числе Castle, LinFu и Microsoft Application Application Block. Фактически, некоторые контейнеры с инверсией контроля имеют в них также некоторые аспектно-ориентированные функции.

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

Ответ 2

Мой совет? Оберните интерфейсы ведения журнала в свои собственные. Я принял зависимость от Log4Net один раз, сожжен и должен был реорганизовать много моих проектов из-за этого.

Ответ 3

Это не будет полным ответом, но одно соображение будет заключаться в том, что если вы введете свой ILog через конструктор вашего класса, вы можете затем издеваться над этой базой ведения журнала для тестирования вашего устройства. Другие мысли... Узел свойств для передачи в ILog означает, что вы не можете регистрировать действия из конструктора. Кроме того, вы не знаете наверняка, имеет ли ваш экземпляр доступ к ILOG, что означает, что вы должны обернуть каждый вызов тестом на действительный экземпляр ILog.

Ответ 4

Я хотел бы вводить его и использовать интерфейс. Главным образом для облегчения тестирования. Сделать легче заменить макет или заглушку при тестировании объекта-потребителя.

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

Я не вижу, где использование метода factory не может работать с контейнером, однако он затем тестирует потребительский класс в зависимости от правильной конфигурации этого метода factory.