Подтвердить что ты не робот

Что это значит в Prism/Unity: Container.Resolve <ShellPresenter>()

(из файла StockTraderRIBootstrapper.cs в примере приложения Prism V2 StockTrader)

В чем разница между этим:

ShellPresenter presenter = new ShellPresenter();

и это:

ShellPresenter presenter = Container.Resolve<ShellPresenter>();
  • Я понимаю, что второй пример касается обработки контейнера, как factory, идя к нему, говоря: "Мне нужен экземпляр объекта типа ShellPresenter".
  • Но что, если, например, Мне нужно отправить параметры, что будет эквивалентно "новому ShellPresenter (1, true)" и т.д.?
  • И поскольку контейнеру нужно сообщить о ShellPresenter, я ожидал найти где-нибудь в проекте место, где класс ShellPresenter регистрируется в контейнере, например. Я ожидал

что-то вроде этого:

Container.RegisterType<IShellPresenter, ShellPresenter>();

но не нашел его нигде. Итак, как контейнер узнает об этих типах, чтобы он мог. Разверните их? Я перестроил это в своем собственном проекте и получил ошибку "Разрешение ошибки с ошибкой" , где мне нужно зарегистрировать эту зависимость затем?

Любое направление/обсуждение здесь было бы полезно.

Необъяснимый ответ:

Итак, в bootstrapper, когда я регистрирую сам Shell:

protected override void ConfigureContainer()
{
    Container.RegisterType<IShellView, Shell>();
    base.ConfigureContainer();
}

тогда Контейнер может разрешить тип ShellPresenter. Итак, как зарегистрирован тип ShellPresenter, когда я регистрирую тип Shell?

Удивительный ответ:

Итак, выясняется, что вам не нужно регистрировать тип, который вы пытаетесь решить, но вам нужно зарегистрировать типы параметров (интерфейса), переданные конструктору типа, который вы пытаетесь разрешить, т.е. поскольку я вставляю интерфейс IShellView в свой конструктор ShellPresenter, мне нужно было зарегистрировать тип IShellView, а не тип IShellPresenter:

public ShellPresenter(IShellView view) ...

Я тестировал это, пытаясь решить тип Tester:

Tester tester = Container.Resolve<Tester>();

Пока я вставляю SomeClass в свой конструктор:

public Tester(ISomeClass someClass)

Я получаю неразрешенные ошибки зависимостей, пока я не зарегистрирую SomeClass с контейнером:

Container.RegisterType<ISomeClass, SomeClass>();

Тогда он работает. Это так же удивительно, как и образовательное. Нужно утонуть. Я собираюсь попить кофе и подумать об этом некоторое время.

Если кто-то может понять, почему это так, это было бы очень полезно.

4b9b3361

Ответ 1

Вы понимаете основы.

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

Точка контейнеров DI состоит в том, что вы можете настроить их для изменения типа, который будет разрешен для конкретного интерфейса, без перекомпиляции вашего программного обеспечения. Пример кода, который вы предоставили для настройки поставщика, не может быть изменен во время выполнения. Именно поэтому большинство инжекторов зависимостей позволяют вам настраивать их в файле app.config/web.config/некоторых других внешних конфигурациях. Таким образом, вы можете перенастроить свое приложение для ввода другого типа без перекомпиляции, что является истинной мощью инфраструктур DI, таких как Unity.

Ответ 2

Если вы попытаетесь разрешить конкретный класс и не зарегистрировали экземпляр или подкласс для его удовлетворения, то Unity построит для вас экземпляр конкретного класса, разрешив любые зависимости, которые он имеет.

Поэтому, когда вы запрашиваете ShellPresenter и не зарегистрировали его, Unity просто обновляет ShellPresenter для вас с помощью ShellView в качестве параметра.

Ответ 3

Ну, я не могу ответить за Untiy, но для Castle Windsor регистрация может быть в файле app.config/web.config. Также есть возможность добавлять параметры в config xml.

Это позволяет вам изменить реализацию и конфигурацию объекта, не перекомпилируя приложение.

Ответ 4

В Unity действительно существует метод Container.RegisterType<TFrom, TTo>(), который регистрирует типы во время выполнения. Скорее всего, это происходит с использованием файла конфигурации XML, но он работает.

Интересно, что в Unity нет метода Container.Resolve<T>(params object[] parameters) -type для разрешения типа с определенными значениями параметров конструктора. Unity построен поверх ObjectBuilder, который является библиотекой команд P & P для создания и создания объектов (IIRC был первоначально написан для ObjectSpaces, но теперь был значительно расширен). ObjectBuilder дает вам возможность вводить зависимости различными способами, в том числе через конструктор, поэтому вы можете сказать, например, что вы передадите новый экземпляр типа, в котором он зависит, в конструктор разрешенного типа; но этот тип также должен быть зарегистрирован. Вы также можете передавать экземпляры зарегистрированных типов (зарегистрированный экземпляр/синглтон и т.д.). Но AFAICS не может просто дать ему значение, чтобы пройти.

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

Я не могу говорить за Windsor, StructureMap или другие, что может позволить вам это сделать. Я даже не могу сказать категорически, что Unity не имеет никакого способа сделать это, так как я в этом совершенно новый, но IIRC Chris Tavares, который в основном строил Unity, время от времени болтается здесь, так что, возможно, ответьте на это: -)