Добре дошли в част 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(); и така нататък. Има два проблема с това:
- Много тясно свързване между всеки компонент
- Може да има споделено състояние и не можем да го използваме, когато създаваме отделни екземпляри на това състояние
Има някои възможни хакерски заобиколни решения, но инжектирането на зависимости и инверсията на контрола ни предлага много по-добро решение.
Брайън обяснява процеса, през който преминава 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
Има три варианта:
- инстанция — просто нов обект, след което го регистрирайте в контейнера
- единичен
- преходен
За допълнителна информация вижте „Живот на обекта, дъщерни контейнери и поведение по подразбиране“
Използване на конфигурация на рамката за изрично регистриране на типове
Тази демонстрация актуализира отново нашата функция за конфигуриране и виждаме как да приложим всяка от трите опции, описани в предишния урок.
Използване на 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.