2017-02-07 7 views
3

Я знаком с Aurelia и инъекцией зависимостей. Тем не менее, я не понимаю следующую строку из книги «Обучающая Аурелия» на Packtpub.com в главе «Включение зависимостей».Что такое контейнеры в инъекции зависимостей Aurelia

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

Я использую DI, как в примере, в книге:

import {PersonService} from 'app-services'; 
import {Person} from 'models'; 
import {autoinject} from 'aurelia-framework'; 

@autoinject 
export class PersonList { 

constructor(private personService: PersonService) { 
} 

getPeople(){ 
    return this.personService.getAll(); 
} 
} 

Но где контейнер вписывается в это? Я никогда не ссылался на контейнер в коде. Я не создал дочерние контейнеры. В нем говорится: «Каждый дочерний контейнер наследует службы своего родителя». У меня есть компоненты со многими дочерними компонентами, которые представляют собой отдельные виды и режимы просмотра. Я не понимаю, как в него вписываются контейнеры. Как бы viewmodels обращались к службам родителя?

Я что-то упустил?

ответ

4

Аурелия имеет реализацию зависимостей инжекционного контейнера, который он использует для создания экземпляра ViewModels и многие из служб приложений, которые являются частью системы или письменными разработчиками. Как правило, вам не нужно использовать контейнер непосредственно, потому что система соглашений Aurelia использует контейнер для создания моделей просмотра и служб от вашего имени, а @inject и @autoinject не нужно настраивать контейнер вручную.

Что представляет собой контейнер для инъекций ?Ну контейнер другое слово для инжектора:

Инжектор представляет услуги в клиенте. Часто он также создает клиента. Инжектор может связывать вместе очень сложный граф объектов, обрабатывая объект, подобный клиенту, а затем как услугу для другого клиента. Инжектор может фактически быть множеством объектов, работающих вместе, но не может быть клиентом. На инжектор могут ссылаться другие имена, такие как: сборщик, поставщик, контейнер, завод, строитель, весна, строительный код или основной. - https://en.wikipedia.org/wiki/Dependency_injection

контейнерная система Аурелии является иерархическим, что означает, когда вы @inject или @autoinject что-то, текущий контейнер (ребенок) будет произведен поиск элемента и, если он не найден, будет произведен поиск родительского контейнера и так и до тех пор, пока элемент не будет найден или не будет удален корневой контейнер, и в этом случае Aurelia построит новый экземпляр запрашиваемого элемента.

В вашем фрагменте кода у вас есть:

import {PersonService} from 'app-services'; 
import {Person} from 'models'; 
import {autoinject} from 'aurelia-framework'; 

@autoinject 
export class PersonList { 

    constructor(private personService: PersonService) { 
    } 

    getPeople(){ 
    return this.personService.getAll(); 
    } 
} 

Предполагая, что это вид-модель специальный элемент, который вы используете, как это: <person-list></person-list>, вот что произойдет, когда Аурелия инстанцирует PersonList.

  1. Детский контейнер будет создан из текущего контейнера (подробнее о том, что представляет собой «текущий контейнер» позже). Эквивалент вызова container.createChildContainer(). Мы будем называть этот дочерний контейнер «childContainer».
  2. Контекстные элементы будут зарегистрированы в дочернем контейнере, таком как элемент DOM (представление) для модели представления PersonList. Это эквивалент вызова childContainer.registerInstance(Element, personListDomElement). Зачем? Потому что это позволяет разработчикам @inject(Element) (или эквивалент @autoinject).
  3. Как только дочерний контейнер сконфигурирован, он используется для создания экземпляра PersonList. Эквивалент вызова:

    personList = childContainer.invoke(PersonList); 
    childContainer.registerInstance(PersonList, personList); 
    
  4. Ребенка контейнер не имеет ничего зарегистрированного с помощью клавиши «PersonService», так что это будет искать родительский контейнер, пока он не найден или не может быть найден, в этом случае Aurelia будет построен новый экземпляр PersonService и зарегистрируйте его в корневом контейнере, чтобы экземпляр можно было повторно использовать в последующих поисках.

  5. Список просмотров и вид списка лиц составлены механизмом шаблонов, а события создания, привязки, присоединения и т. Д. Происходят.

Бонус: раньше я упомянул ребенок контейнер будет создан из текущего контейнера ... Каждый Aurelia приложение имеет контейнер «корневой уровень», что каждый ребенок контейнер нисходит из, прямо или косвенно. Основные сервисы Aurelia зарегистрированы в корневом контейнере: BindingEngine, ObserverLocator, TaskQueue и многие другие. Это то, что позволяет разработчикам писать @inject(TaskQueue) и получить тот же экземпляр TaskQueue, который использует инфраструктура Aurelia внутри. В любом случае, когда создается пользовательский элемент или настраиваемый атрибут, дочерний контейнер используется для создания настраиваемого элемента или настраиваемого атрибута. Если этот пользовательский элемент содержит другой пользовательский элемент, дочерний контейнер будет создан из текущего дочернего контейнера и используется для создания экземпляра дочернего пользовательского элемента и так далее.Другими словами, «текущий контейнер» зависит от того, насколько глубоко ваш компонент находится в иерархии вложенных настраиваемых элементов и пользовательских атрибутов.

Ссылки:

2

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

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

Есть помощники, которые вы можете использовать, чтобы предоставить контейнеру информацию о том, как он должен обрабатывать вещи. Вы получаете поведение по умолчанию, используя @autoinject, но если вам нужно быть более конкретным, вы можете переключиться на декоратор @inject и сделать что-то вроде @inject(Parent.of(Foo), Optional.of(Bar)) или что-то в этом роде. Это даст вам экземпляр класса Foo, который был создан в родительском контейнере, и сообщит контейнеру: «Мне бы хотелось иметь экземпляр Bar, но это здорово, если вы не можете его создать для меня».

Если вам нужен доступ к виртуальной машине родителя, вы можете использовать Parent.of(), чтобы получить ее в дочернем компоненте. Обратите внимание, что это одна из тех вещей типа «Обработка с осторожностью», потому что вы привязываете дочерний компонент непосредственно к реализации виртуальной машины родителя, и компонент не сможет создать (и, возможно, отключить приложение), если вы используете его внутри страницу/компонент, который имеет другой класс VM.

Для получения дополнительной информации, пожалуйста, ознакомьтесь с нашими документами: http://aurelia.io/hub.html#/doc/article/aurelia/dependency-injection/latest/dependency-injection-basics