1

Я читал различные статьи о IoC, DIP, DI и Locator, но я немного смущен, что связано с тем, что в некоторых статьях есть слишком неопределенные примеры, а некоторые другие статьи имеют только некоторые конкретные примеры без упоминания других случаев.Путаница о DI, IoC и локаторах сервисов

Не могли бы вы прояснить это для меня, глядя на приведенные ниже примеры и коротко объяснив, какие примеры соответствуют тому образцу?

  • вручную проходя интерфейс конструктора:

    class Consumer 
    { 
        public Consumer(IStore store){...} 
    } 
    ... 
    
    Consumer c = new Consumer(new ConcreteStore()); 
    
  • так же, как и в первом примере, но с помощью некоторых третьей стороной библиотеки (Unity, Виндзор, Ninject)

  • такой же, как первый пример, но с использованием класса BaseStore вместо интерфейса IStore

  • Пропускная зависимость от какой-либо другой метод, а не конструктор:

    class Consumer 
    { 
        public BySomething(IStore store){...} 
    } 
    ... 
    
    Consumer c = new Consumer(); 
    c.BySomething(new ConcreteStore()); 
    
  • прохождение зависимости замаскированы внутри какой-либо другой интерфейс (бонус для этого решения - когда некоторые другие вещи, которые изобретены в «мире» и потребитель желает использовать их, мы не 't нужно изменить аргумент конструктора, но просто обновить IWorld; и мы можем полностью заменить весь мир с чем-то еще при тестировании):

    interface IWorld 
    { 
        IDictionary<string,IStore> Stores { get; set; } 
        IDictionary<string,ICityMap> Maps { get; set; } 
        ... 
    } 
    
    class Consumer 
    { 
        public Consumer(IWorld world){...} 
        public BySomething(string store, string city){...} 
    } 
    
    ... 
    
    IWorld myWorld = new HeavenlyWorld(); 
    ... // adding stores, maps and whatnot 
    
    Consumer c = new Consumer(myWorld); 
    

    суб-вопрос: в данном случае, является IWorld локатор услуг или не совсем?

  • передавая функцию обратного вызова или делегата (.NET Действие в данном случае):

    c.BySomething(store, city, new Action(() => {...})); 
    

    Я добавил этот случай, потому что в статье Inversion of Control гласит, что каждый обратный вызов IoC. Это правда?

+0

Ваш вопрос: 'IWorld' является локатором сервисов? –

+0

Это вопрос об одном конкретном случае. Наиболее важный вопрос: какая из этих точек совпадает с какими из шаблонов (DI, DIP, IoC, SL). – JustAMartin

ответ

1

Каждый раз, когда вы передаете зависимость как аргумент конструктора/метода, это Dependecy Injection. Он может быть ручным, как и в большинстве ваших примеров, или автоматически использовать контейнер DI, например IoC Container.

Использование контейнера означает, что объекты с использованием депо построены контейнером. Вы можете спросить контейнер непосредственно для этой службы, и в этом случае есть статическое свойство или метод (подумайте, что DependecyResolver в asp.net mvc), который предоставляет эту услугу. В этом случае вы используете шаблон Service Locator. IWork в вашем примере не является локатором, это просто зависимость.

Чтобы продолжить использование примера преобразователя зависимостей, вы регистрируете все соответствующие типы в контейнере, контейнер создается, а затем регистрируется как преобразователь зависимости. Затем фреймворк asp.net mvc использует resolver (Service Locator - SL) для создания экземпляров контроллеров, представлений и всех необходимых им депо.

Чтобы использовать шаблон SL, это нормально как часть фреймворка, но это не нормально, если вы используете его в своем приложении для создания объектов, потому что он связывает код с локатором. Иногда это единственное решение, но на 99% вы просто анти-шаблон.

+0

Можно ли уменьшить его до минимума и вызвать его DI, когда мы передаем аргументы примитивных типов данных (int, string) для некоторой функции? В конце концов, эта функция зависит от этих данных и может даже модифицировать эти данные (если мы пройдем через ref), давая нам какой-то примитивный обратный вызов. Но делает ли это DI и IoC? И это также принцип инверсии зависимостей или нет? – JustAMartin

+1

Нет, DI не связан с передачей args методу. Речь идет о поставке необходимых «сервисов», зависимостей, которые должны быть абстракциями, а не конкретными типами. IoC основан на абстракциях, потому что объект более высокого уровня определяет необходимую абстракцию, тогда как нижний объект lvl обеспечивает реализацию (неизвестный высшему объекту и, следовательно, развязанный). С конкретными типами нижний объект lvl находится под контролем, в то время как здесь управление отменяется. – MikeSW

2

Все, что вы указали, является формой инъекции зависимостей.

  1. "бедняка" DI
  2. DI с помощью контейнера IoC
  3. "бедняка" DI снова. DI работает независимо от того, используете ли вы интерфейс или абстрактный класс.
  4. Метод Инъекции
  5. Я не уверен, что вы здесь просите. Похоже, вы хотите изменить экземпляр IWorld во время выполнения, что может быть примером для Property Injection вместо Constructor Injection. Свойства часто используются для необязательных зависимостей или тех, которые могут быть изменены. Независимо от того, устанавливаете ли вы эту зависимость во время выполнения с помощью Service Locator или другими средствами, зависит от вас. Еще одна вещь, которую следует учитывать, - это то, что IWorld может просто зависеть от контекста, и в этом случае вы можете сделать инъекцию конструктора контекста, детали которой не входят в сферу этого вопроса.
  6. Относится к DI
+0

Но является ли 6-й пункт все еще действительным случаем IoC? Я спрашиваю об этом, потому что статья здесь http://devmethodologies.blogspot.com/2012/06/inversion-of-control.html гласит, что функции обратного вызова можно считать IoC. Это правильно? – JustAMartin

+1

Я вижу пункт статьи. Технически это IoC, но это не то, что приходит на ум в контексте контейнеров DI и IoC. –

Смежные вопросы