Зависимость впрыска с Ninject, MVC 3 и использование шаблона локатора службы

StackOverflow https://stackoverflow.com/questions/4607425

Вопрос

Что-то, что меня, так как я прочитал ответ на другой вопрос стойки (точный ускользнет на мне сейчас), где пользователь что-то подобноеЕсли вы звоните на сервисный локатор, вы делаете это неправильно."

Это был кто-то с высокой репутацией (в сто тысяч, я думаю), поэтому я склонен думать, что этот человек может знать, о чем они говорят. Я использовал di для моих проектов, поскольку сначала начал учиться об этом и насколько хорошо оно относится к тестированию подразделения и чего нет. Это то, что я довольно комфортно, и я думать Я знаю, что я делаю.

Тем не менее, есть много мест, где я использовал сервисный локатор для разрешения зависимостей в моем проекте. Как только Prime пример исходит от моих реализаций ModelBinder.

Пример типичного связующего модели.

public class FileModelBinder : IModelBinder {
    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext) {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue("id");

        IDataContext db = Services.Current.GetService<IDataContext>();
        return db.Files.SingleOrDefault(i => i.Id == id.AttemptedValue);
    }
}

не реальная реализация - просто быстрый пример

Поскольку реализация ModelBinder требует нового экземпляра, когда связующее является первый Запрошено, невозможно использовать инъекцию зависимости на конструкторе для этой конкретной реализации.

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

Еще одна проблема, в которой я недавно (что я разместил вопрос о том, что все мои контроллеры требуют экземпляра IDataContext, который я использовал di для - но один Метод действий Требуется другой экземпляр IDataContext. К счастью, Ninject пришел к спасению с именованной зависимостью. Однако это было похоже на клову и не реальное решение.

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

То, как я в настоящее время понимаю это - и это может быть не так, как и в том, это то, что, по крайней мере, в MVC, регуляторное управление ищет конструктора для контроллера и вызывает самого сервисного локатора, чтобы получить необходимые зависимости, а затем передавать их. Однако Я могу понять, что не все классы и то, что не имеют завода для их создания. Так мне кажется, что какой-то шаблон сервисного локатора приемлема ... Но ...

  1. Когда это не приемлемо?
  2. Какую картину я должен быть в порядке, когда я должен переосмыслить, как я использую шаблон сервисного локатора?
  3. Является ли моя реализация ModelBinder неправильно? Если это так, что мне нужно научиться исправлять это?
  4. В другой вопрос по линиям этого пользователя Марк, Кавалан Рекомендуется абстрактный фабрик - как это относится?

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

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

Я не ищу код, чтобы починить свой пример реализации - я ищу изучение, ищу объяснение, чтобы исправить мое недостаточное понимание.

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

Это было полезно?

Решение

Рассмотрим следующее:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass(IMyInterface myInterface, IMyOtherInterface myOtherInterface)
  {
    // Foo

    _myInterface = myInterface;
    _myOtherInterface = myOtherInterface;
  }
}

С помощью этой конструкции я могу выразить требования зависимости для моего типа. Сам тип не несет ответственности за то, что знает, как создать какое-либо из зависимостей, они дают ему (вводят) любым разрешением механизма [Обычно контейнер IOC]. В то время как:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass()
  {
    // Bar

    _myInterface = ServiceLocator.Resolve<IMyInterface>();
    _myOtherInterface = ServiceLocator.Resolve<IMyOtherInterface>();
  }
}

Наш класс в настоящее время зависит от создания экземпляров SPEMFIC, но через делегацию в сервисный локатор. В этом смысле расположение услуг можно считать анти-образцовый Поскольку вы не выставляете зависимости, но вы разрешаете проблемы, которые могут быть пойманы путем компиляции, чтобы позвонить в протяжении времени выполнения. (Хороший читал здесь). Вы скрываете сложности.

Выбор между тем или иным действительно зависит от того, что ваше здание сверху и услуг обеспечивает. Как правило, если вы строите приложение с нуля, я бы выбрал ди все время. Он улучшает ремонтопригодность, способствует модульности и облегчает тестирование типов в целом. Но, принимая ASP.NET MVC3 в качестве примера, вы можете легко реализовать SL как запеченный в дизайн.

Вы всегда можете пойти на композитный дизайн, где вы можете использовать IOC / DI с SL, очень похожим на использование Общие услуги локатор. Отказ Ваши компонентные детали могут быть подключены через ди, но выставлены через SL. Вы могли бы даже бросить композицию в смеси и использовать что-то вроде как управляемая структура расширяемости (которая сама поддерживает DI, но также может быть подключено к другим контейнерам IOC или локаторам обслуживания). Это большой выбор дизайна, чтобы сделать, в целом моя рекомендация будет для МОК / ди, где это возможно.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top