интерфейсы внедрения и регистрации зависимостей - PullRequest
27 голосов
/ 07 февраля 2009

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

Внедрение зависимостей, кажется, утверждает, что внешние зависимости должны быть внедрены извне (конструкторы или установщики свойств), поэтому я должен взять экземпляр ILog в конструкторе и использовать в классе? Я должен рассмотреть регистрацию дополнительной зависимости и получить ее в сеттере? Я настаиваю на слишком большой гибкости, допуская изменение интерфейса ведения журнала, и я должен просто взять жесткую зависимость от конкретного интерфейса ведения журнала (например, создать статическую переменную ILog через вызов метода фабрики)? Может ли этот метод фабрики вызвать в контейнер, чтобы получить реализацию 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()
  {
  }
}

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

Ответы [ 4 ]

4 голосов
/ 07 февраля 2009

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

4 голосов
/ 07 февраля 2009

Здорово, что вы смотрите на инверсию управления и внедрение зависимостей.

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

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

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

3 голосов
/ 07 февраля 2009

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

0 голосов
/ 07 февраля 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...