A szögfüggőség injekciója példákkal magyarázható

Mi a függőségi injekció?

Motiváció

A függőségi injekciót egyszerűbben DI-nek nevezik. A paradigma az egész Szögletben létezik. Rugalmas, tesztelhető és módosítható kódot biztosít. Az osztályok örökölhetik a külső logikát anélkül, hogy tudnák, hogyan kell létrehozni. Ezen osztályok bármely fogyasztójának sem kell semmit sem tudnia.

A DI megmenti az osztályokat és a fogyasztókat is attól, hogy többet kell tudniuk a szükségesnél. Mégis, a kód ugyanolyan moduláris, mint korábban volt, a DI-t szögben támogató mechanizmusoknak köszönhetően.

A szolgáltatások a DI kulcsfontosságú jótevői. A különböző fogyasztók injekciójának paradigmájára támaszkodnak . Ezek a fogyasztók ezután igénybe vehetik a szolgáltatás nyújtotta előnyöket és / vagy továbbíthatják máshová.

A szolgáltatás nincs egyedül. Irányelvek, csövek, alkatrészek és így tovább: az Angular minden vázlata valamilyen módon előnyben részesíti a DI-t.

Injektorok

Az injektorok olyan adatstruktúrák, amelyek utasításokat tárolnak, amelyek részletezik a szolgáltatások formáját és módját. Közvetítőként működnek az Angular DI rendszeren belül.

A modul-, irányelv- és alkatrészosztályok az injektorok specifikus metaadatait tartalmazzák. Ezen osztályok mindegyikéhez új injekciós eset társul. Ily módon az alkalmazásfa tükrözi az injektorok hierarchiáját.

A providers: []metaadatok olyan szolgáltatásokat fogadnak el, amelyek regisztrálódnak az osztály injektoránál. Ez a szolgáltató mező tartalmazza az injektor működéséhez szükséges utasításokat. Egy osztály (feltételezve, hogy függőségekkel rendelkezik) példányosítja a szolgáltatást azzal, hogy az osztályát veszi át az adattípusaként. Az injektor összehangolja ezt a típust, a létrehozza a szolgáltatás egy példányát az osztály nevében.

Természetesen az osztály csak azt tudja beavatkozni, amire az injektornak utasításai vannak. Ha az osztály saját injektorának nincs regisztrálva a szolgáltatása, akkor megkérdezi a szülőjét. Így tovább és így tovább, amíg el nem éri az injekciót a szolgáltatással vagy az alkalmazás gyökérzetével.

A szolgáltatások az alkalmazás bármelyik injektoránál regisztrálhatnak. A szolgáltatások providers: []az osztálymodulok, irányelvek vagy összetevők metaadat-mezőjébe tartoznak. A „gyerekek képesek az osztályba bejegyzett szolgáltatást beavatkozni” osztályba tartozó injektor. Végül is a gyermekinjektorok visszaesnek a szülőinjektorokba.

Függőségi injekció

Vessen egy pillantást az egyes osztályok csontvázaira: szolgáltatás, modul, irányelv és alkatrész.

// service import { Injectable } from '@angular/core'; @Injectable({ providedIn: /* injector goes here */ }) export class TemplateService { constructor() { } }
// module import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; @NgModule({ imports: [ CommonModule ], declarations: [], providers: [ /* services go here */ ] }) export class TemplateModule { }
// directive import { Directive } from '@angular/core'; @Directive({ selector: '[appTemplate]', providers: [ /* services go here */ ] }) export class TemplateDirective { constructor() { } }
//component import { Component } from '@angular/core'; @Component({ selector: 'app-template', templateUrl: './template.component.html', styleUrls: ['./template.component.css'], providers: [ /* services go here */ ] }) export class TemplateComponent { // class logic ... }

Minden csontváz regisztrálhatja az injektor szolgáltatásait. Tény, TemplateService van egy szolgáltatás. Az Angular 6-tól kezdve a szolgáltatások @Injectablemetaadatok segítségével regisztrálhatják magukat az injektoroknál .

Mindenesetre

Figyelje meg a providedIn: string( @Injectable) és providers: []( @Directive, @Componetés @Module) metaadatokat. Megmondják az injektoroknak, hogy hol és hogyan kell létrehozni egy szolgáltatást. Ellenkező esetben az injektorok nem tudnák, hogyan lehet példányosítani.

Mi van, ha egy szolgáltatás függőségekkel rendelkezik? Hova mennének az eredmények? A szolgáltatók megválaszolják ezeket a kérdéseket, hogy az injektorok megfelelően tudjanak példát mutatni.

Az injektorok alkotják a DI keret gerincét. Utasításokat tárolnak a szolgáltatások példányosítására, hogy a fogyasztóknak ne kelljen. Szolgáltatási példányokat fogadnak, anélkül, hogy bármit is tudniuk kellene a forrásfüggőségről!

Azt is meg kell jegyeznem, hogy más injektor nélküli vázlatok továbbra is felhasználhatják a függőségi injektálást. Nem tudnak további szolgáltatásokat regisztrálni, de továbbra is képesek az injektorok részéről.

Szolgáltatás

A providedIn: stringmetaadatok @Injectablemeghatározzák, hogy melyik injektornál kell regisztrálni. Ennek a módszernek a használatával és attól függően, hogy a szolgáltatást megszokják-e, a szolgáltatás regisztrálhat vagy nem regisztrálhat az injektornál. Szögletes hívja ezt a fát rázó .

Alapértelmezés szerint az érték értéke ‘root’. Ez az alkalmazás gyökérinjektorát jelenti. Alapvetően a mező beállítása úgy, hogy ‘root’a szolgáltatás bárhol elérhető legyen.

Gyors megjegyzés

Mint korábban említettük, a gyermekinjekciós gyógyszerek visszalépnek szüleikhez. Ez a tartalék stratégia biztosítja, hogy a szülőknek ne kelljen újra regisztrálniuk minden injekciót. A koncepció és a Szolgáltatások és injektorok című cikkben találja meg ennek a koncepciónak a szemléltetését.

A regisztrált szolgáltatások egyedülállóak . Vagyis a szolgáltatás példányosítására vonatkozó utasítások csak egy injektoron léteznek. Ez feltételezi, hogy máshol nem volt kifejezetten regisztrálva.

Modul, irányelv és alkatrész

A moduloknak és az alkatrészeknek mindegyiküknek megvan a maga injektor-példánya. Ez nyilvánvaló a providers: []metaadatok mezőjében. Ez a mező egy tömb szolgáltatást vesz fel és regisztrálja őket a modul vagy az összetevő osztály injektoránál. Ez a megközelítés történik a @NgModule, @Directivevagy @Componentfestő.

Ez a stratégia mellőzi a fa rázkódását vagy a fel nem használt szolgáltatások opcionális eltávolítását az injektorokból. A szervizpéldányok a modul vagy alkatrész élettartamáig élnek az injektoraikon.

Hivatkozások ösztönzése

A DOM-ra való hivatkozások bármely osztályból példamutathatók. Ne feledje, hogy a referenciák továbbra is szolgáltatások. A hagyományos szolgáltatásoktól abban különböznek, hogy valami más állapotot képviselnek. Ezek a szolgáltatások olyan funkciókat tartalmaznak, amelyek kölcsönhatásba lépnek a referenciájukkal.

Az irányelveknek állandóan szükségük van a DOM hivatkozásokra. Az irányelvek ezeken a hivatkozásokon keresztül végeznek mutációkat gazdaelemeiken. Lásd a következő példát. Az irányelv injektora példányosítja a gazdagép hivatkozását az osztály konstruktorába.

// directives/highlight.directive.ts import { Directive, ElementRef, Renderer2, Input } from '@angular/core'; @Directive({ selector: '[appHighlight]' }) export class HighlightDirective { constructor( private renderer: Renderer2, private host: ElementRef ) { } @Input() set appHighlight (color: string) { this.renderer.setStyle(this.host.nativeElement, 'background-color', color); } }
// app.component.html 

Highlighted Text!

Renderer2is példányos lesz. Melyik injektorból származnak ezek a szolgáltatások? Nos, minden szolgáltatás forráskódja származik @angular/core. Ezeknek a szolgáltatásoknak ezt követően regisztrálniuk kell az alkalmazás gyökérinjektorában.

import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { HighlightDirective } from './directives/highlight.directive'; @NgModule({ declarations: [ AppComponent, HighlightDirective ], imports: [ BrowserModule ], providers: [], bootstrap: [ AppComponent ] }) export class AppModule { }

Egy üres szolgáltató tömb !? Nem félni. Az Angular sok szolgáltatást automatikusan regisztrál a gyökérinjektorral. Ez magában foglalja ElementRefés Renderer2. Ebben a példában a gazdagép elemét annak felületén keresztül kezeljük, amely a ElementRef. Renderer2frissíthetjük a DOM-ot az Angular nézetmodelljén keresztül.

You can read more about views from this article. They are the preferred method for DOM/view updates in Angular applications.

It is important recognize the role that injectors play in the above example. By declaring variable types in the constructor, the class obtains valuable services. Each parameter’s data type maps to a set of instructions within the injector. If the injector has that type, it returns an instance of said type.

Instantiating Services

The Services and Injectors article explains this section to an extent. Though, this section rehashes the previous section or the most part. Services will often provide references to something else. They may just as well provide an interface extending a class’ capabilities.

The next example will define a logging service that gets added to a component’s injector via its providers: [] metadata.

// services/logger.service.ts import { Injectable } from '@angular/core'; @Injectable() export class LoggerService { callStack: string[] = []; addLog(message: string): void { this.callStack = [message].concat(this.callStack); this.printHead(); } clear(): void { this.printLog(); this.callStack = []; console.log(“DELETED LOG”); } private printHead(): void  null);  private printLog(): void { this.callStack.reverse().forEach((log) => console.log(message)); } }
// app.component.ts import { Component } from '@angular/core'; import { LoggerService } from './services/logger.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', providers: [LoggerService] }) export class AppComponent { constructor(private logger: LoggerService) { } logMessage(event: any, message: string): void { event.preventDefault(); this.logger.addLog(`Message: ${message}`); } clearLog(): void { this.logger.clear(); } }
// app.component.html 

Log Example

SUBMIT

Delete Logged Messages

CLEAR

Focus on the AppComponent constructor and metadata. The component injector receives instructions from the provider’s metadata field containing LoggerService. The injector then knows what to instantiate LoggerService from requested in the constructor.

The constructor parameter loggerService has the type LoggerService which the injector recognizes. The injector follows through with the instantiation as mentioned.

Conclusion

Dependency injection (DI) is a paradigm. The way it works in Angular is through a hierarchy of injectors. A class receives its resources without having to create or know about them. Injectors receive instruction and instantiate a service depending on which one was requested.

DI shows up a lot in Angular. The official Angular documentation explains why the paradigm is so prevalent. They also go on to describe the numerous use-cases for DI in Angular way beyond what was discussed in this article. Check it out by clicking below!

More on dependency injection:

  • Intro to Angular dependency injection
  • Quick intro to dependency injection