Добре дошли в част 4 от тази поредица, разглеждаща курса на Pluralsight Основи на Aurelia от Brian Noyes.

Брайън е технически директор и архитект в Solliance, експертна компания за разработка на технологични решения.

Брайън е регионален директор на Microsoft и MVP и е специализиран в богати клиентски технологии, както и изграждане на услуги, които ги поддържат с WCF и ASP.NET Web API.

Можете да следвате Brian чрез неговия блог на адрес http://briannoyes.net

Още в тази серия:

Част 1 — Предпоставки за Aurelia
Част 2 — Първи стъпки
Част 3 — Внедряване на MVVM

Цел на инжектирането на зависимост и свързани модели

Инжектирането на зависимост се отнася най-вече за наличието на хлабава връзка между зависимите компоненти.

Брайън също споменава няколко тясно свързани модела: Инверсия на контрола и местоположението на услугата

Има и много други курсове на Pluralsight, които обхващат инжектиране на зависимости и/или инверсия на контрола.

Тези, които видях и си струват, са:

C# интерфейси от Джереми Кларк
Инжектиране на зависимост на RequireJS и зареждане на модули от Джеф Валор
Създаване на JavaScript модули с Browserify от Джеф Валор
Разбиране на ASP.NET Core от Роланд Гуийт
SOLID Принципи на обектно-ориентиран дизайн от Стив Смит
Инверсия на контрола от Джон Сонмез
Практически IoC с ASP.NET MVC4 от Джон Сонмез

За да научите повече за шаблона за локатор на услуги, вижте „Модула за локатор на услуги“ на Джон Браун в курса „Библиотека с шаблони за проектиране“.

Само за много кратко резюме на Service Locator прочетете тази статия в wikipedia.

Вижте също моята страница Дизайнски модели.

Инверсия на инжектиране на контрол/зависимост: проблем и решение

Браян дава пример:

  • Някои потребителски обекти зависят от A
  • A зависи от B и C
  • B зависи от D
  • C зависи от D и E

Грубият начин за прилагане на това е да се актуализира всеки обект преди да бъде използван, т.е. в A ще имаме нов B(); и нов C(); и така нататък. Има два проблема с това:

  1. Много тясно свързване между всеки компонент
  2. Може да има споделено състояние и не можем да го използваме, когато създаваме отделни екземпляри на това състояние

Има някои възможни хакерски заобиколни решения, но инжектирането на зависимости и инверсията на контрола ни предлага много по-добро решение.

Брайън обяснява процеса, през който преминава IoC контейнер в този пример.

Използване на ‘inject’ Decorator в Aurelia

Моделът е:

  • импортирайте необходимите модули
  • използвайте декоратора @inject, предавайки услуга като параметър

Препоръчвам да прочетете средната публикация на Addy Osmani „Exploring ES7 Decorators“ и/или Yehuda Katz „decorators read me“, за да научите повече за Class Decorators.

Браян казва тук, че те са функция на ES2016. Това не е вярно, защото в момента те са просто предложение от етап 1 на ES2017.

Поддържа се от TypeScript и можете да прочетете повече за това в Наръчник за TypeScript.

Браян обяснява, че има алтернативно решение, поддържано от Aurelia, което е статично инжектиране на свойства с масив от имена на типове

статично инжектиране = [SomeService];

Инжектиране на зависимост в действие

Тази демонстрация използва синтаксиса на декоратора на класа, за да инжектира DataCache в конструкторите на клас Event и Events.

Виждаме, че DataCache е споделено състояние и че режимът по подразбиране на инжектиране на зависимости в Aurelia е „singleton“.

Декларативно регистриране на доживотни инстанции в Aurelia

Можем да посочим на класа какъв живот на екземпляра трябва да има в контейнера. Има два основни модела:

  • Singleton — конструиран при първата инжекция, същата препратка се предава в други инжекции
  • Преходен — нов екземпляр, създаден за всяка инжекция

Тъй като режимът по подразбиране е сингълтън, не е необходимо да указвате живота на екземпляра като сингълтън, но можете да го направите изрично, ако предпочитате.

Използване на доживотни декоратори за управление в Aurelia

Браян демонстрира как да използвате преходния декоратор, за да укажете преходно свойство.

Виждаме в регистрационните файлове на конзолата 3 отделни конструкции на DataCache

Изрично регистриране на типове и екземпляри в Aurelia

Има три варианта:

  1. инстанция — просто нов обект, след което го регистрирайте в контейнера
  2. единичен
  3. преходен

За допълнителна информация вижте „Живот на обекта, дъщерни контейнери и поведение по подразбиране“

Използване на конфигурация на рамката за изрично регистриране на типове

Тази демонстрация актуализира отново нашата функция за конфигуриране и виждаме как да приложим всяка от трите опции, описани в предишния урок.

Използване на Resolvers в Aurelia

В момента има 4 готови резолвера. Три от тях са описани в този урок

  • Lazy.of(T) — Вмъква функция за лениво оценяване на зависимостта
  • All.of(T) — Вмъква масив от всички услуги, регистрирани с предоставения ключ
  • Optional.of(T) — Инжектира екземпляр на клас само ако вече съществува в контейнера; нула в противен случай.

Вижте Resolvers в официалната документация, за да научите Parent.of(T)

Мързеливо зареждане и инстанциране на плъгини с Aurelia

Първо демонстрация на използването на Lazy.of(T).

Браян създава клас ImLazy с конструктор и метод doStuff.

Тогава events.js се създава с клас Events и метода createAndUseImLazy.

В events.html има бутон, който извиква createAndUseImLazy

Ефектът от всичко това е да отложи изграждането на зависимия обект до момента, в който трябва да го използваме.

След това демонстрация на All.of(T), която е полезна за плъгини. Може да искаме да регистрираме всички добавки, които са свързани със система на трета страна.

Първо имаме нужда от дефиниция на плъгин. Виждаме клас PlugIn1 с метод doPlugInStuff и друг клас PlugIn2 с друг метод doPlugInStuff.

В main.js виждаме как да импортираме тези типове плъгини и да ги регистрираме като преходни.

Накрая инжектираме All.of(“SuperPlugIn”) в нашия клас Events.

Така че имаме множество екземпляри от различни типове, всички регистрирани под едно и също име „SuperPlugIn“.

Регистриране на глобални зависимости

Това е чудесен начин да избегнете повтарящи се декларации за внос. Ние регистрираме зависимост глобално чрез метода за конфигуриране на приложението.

След това ще бъде достъпен за инжектиране в нашите модули без инструкция за импортиране и може да се използва в нашите изгледи без елемент ‹require›.

Правим това с ключовата дума globalResources.

За повече информация вижте документацията на FrameworkConfiguration.