5

После прочтения приятных ответов в this question, я наблюдал за скринкастами Джастина Этхедге. Все это кажется очень приятным, с минимальной настройкой вы получаете DI прямо из своего кода.Зачем вам нужна инъекция зависимостей без конфигурации?

Теперь вопрос, который до меня доходит, почему: вы хотите использовать инфраструктуру DI, которая не использует файлы конфигурации? Разве это не все, что нужно для использования инфраструктуры DI, чтобы вы могли изменить поведение (так сказать, «стратегия») после создания/освобождения/независимо от кода?

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

ответ

10

Я не думаю, что вы хотите DI-каркас без конфигурации. Я думаю, вам нужен DI-каркас с конфигурацией вам нужно.

Я возьму весну в качестве примера. Назад в «старые времена» мы использовали, чтобы поместить все в файлы XML, чтобы сделать все настраиваемым.

При переключении на полностью аннотированный режим вы в основном определяете, какой компонент ролей yor application содержит. Таким образом, данная услуга может, например, иметь одну реализацию, которая предназначена для «обычной среды выполнения», где есть другая реализация, которая принадлежит в «Запущенной» версии приложения. Кроме того, при проводке для интеграционных тестов вы можете использовать третью реализацию.

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

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

+0

, но как насчет отсутствия конфигурации вообще (как в google guice) - как вы определяете «роли компонента»? – JohnIdol

+0

В прошлый раз, когда я смотрел на изображение, ему не хватало аспект «соглашения по конфигурации», который вы можете получить, смешивая аннотации, xml и роли, что также является причиной того, что я не использую Spring javaconfig. Я действительно предпочитаю смешанную парадигму. Замена xml кодом, который делает то же самое, не сокращает его для меня, возможно, это просто я, будучи близким, но я не вижу, как настройка на основе кода добавит мне ценность. Но я не знаю, можете ли вы создать схему, основанную на соглашениях, в виде. – krosenvold

0

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

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

1

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

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

0

Вы должны прочитать о PRISM in .NET (это лучшие практики для создания составных приложений в .NET). В этих лучших практиках каждый модуль «Expose» их тип реализации внутри общего контейнера. Таким образом, каждый модуль имеет четкую ответственность над «кто обеспечивает реализацию для этого интерфейса».Я думаю, что будет достаточно ясно, когда вы поймете, как работает PRISM.

+0

Прохладный, я посмотрю на это. –

3

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

+0

Не только модульные тесты - это отличный способ развертывания тестовой/dev-версии приложения с макетными компонентами для тех частей, которые вы не хотите тестировать (или показывать клиентам). – Domchi

+0

Правильно, но для чего мне нужен Ninject? –

1

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

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

0

Когда вы используете инверсию управления, вы помогаете сделать свой класс как можно меньше. Допустим, у вас есть служба Windows, которая ждет файлов, а затем выполняет ряд процессов в файле. Один из процессов - преобразовать его в ZIP, затем отправить по электронной почте.

public class ZipProcessor : IFileProcessor 
{ 
    IZipService ZipService; 
    IEmailService EmailService; 

    public void Process(string fileName) 
    { 
    ZipService.Zip(fileName, Path.ChangeFileExtension(fileName, ".zip")); 
    EmailService.SendEmailTo(................); 
    } 
} 

Почему этот класс нужно на самом деле сделать проносясь и электронной почтой, когда вы могли бы посвящены занятия, чтобы сделать это для вас? Очевидно, вы бы этого не сделали, но это только доводка до моей точки :-)

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

Использование D.I.C. вы можете настроить, какие классы реализуют определенные интерфейсы, а затем просто заставить его создать экземпляр для вас, он будет вводить зависимости в класс.

var processor = Container.Resolve<ZipProcessor>(); 

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

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

//Mock the ZIP 
var mockZipService = MockRepository.GenerateMock<IZipService>(); 
mockZipService.Expect(x => x.Zip("Hello.xml", "Hello.zip")); 

//Mock the email send 
var mockEmailService = MockRepository.GenerateMock<IEmailService>(); 
mockEmailService.Expect(x => x.SendEmailTo(.................); 

//Test the processor 
var testSubject = new ZipProcessor(mockZipService, mockEmailService); 
testSubject.Process("Hello.xml"); 

//Assert it used the services in the correct way 
mockZipService.VerifyAlLExpectations(); 
mockEmailService.VerifyAllExceptions(); 

Итак, короче говоря. Вы хотели бы сделать это до 01: Предотвратите, чтобы потребители знали, какой провайдер реализует необходимые ему услуги, а это значит, что вы сразу понимаете, когда читаете код. 02: Сделать модульное тестирование проще.

Пит

+0

Это классный ответ и все, но не совсем ответ на мой вопрос. Я хорошо осведомлен о том, что такое IoC, и что делает инфраструктура DI; Я просто не вижу причины, почему сама конфигурация в коде. –

5

Я на пути с krosenvold, здесь, только с меньшим количеством текста: В большинстве случаев, у вас есть ровно одну реализации за «услугу» требуется. Мы просто не пишем приложений, где каждому объекту требуется 10 или более реализаций каждой службы. Поэтому было бы разумно сказать, что «это реализация по умолчанию, 99% всех объектов, использующих эту службу, будут довольны».

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

Это то, что условно-над-конфигурацией.В большинстве случаев конфигурация представляет собой просто свалку, повторяющую то, что уже должна знать инфраструктура DI :)

В моих приложениях я использую объект класса в качестве ключа для поиска реализаций, а «ключ» - быть реализацией по умолчанию. Если моя инфраструктура DI не может найти переопределение в конфигурации, она просто попытается создать экземпляр ключа. С более чем 1000 «сервисами» мне нужно четыре переопределения. Это было бы много бесполезного XML для написания.

3

Я получил этот комментарий на моем блоге, от Nate Kohari:

рад, что вы планируете использовать Ninject! Ninject занимает позицию, что конфигурация вашего DI-каркаса фактически является частью вашего приложения и не должна публично настраиваться. Если вы хотите, чтобы определенные привязки были настроены на , вы можете легко сделать свои модули Ninject, прочитав ваш app.config. Имея ваши привязки в коде, вы сохраняете из многословия XML и дает тип безопасности, рефакторизуемость и intellisense.