天天看點

Angular 依賴注入架構裡 useExisting 和 useClass 的使用場景

Angular 依賴注入架構裡 useExisting 和 useClass 的使用場景

從上圖能看出,所有注入的示例都通過factory方法傳回,隻是factory方法的實作有所差異。

As we can see in the picture above all of providers can be presented similar useFactory. When it’s the time to get an instance of provider angular just calls factory function.

一些例子:

{provide: Class1, useClass: Class1}

1

等價于:

Class1

而:

{provide: Class1, useClass: Class3}

you can configure, that when a constructor requests Class1 Angular DI creates an instance of Class3 and passes it to the constructor.

當構造函數的參數需要傳入Class1時,Angular DI傳入一個Class3的框執行個體到構造函數裡。

而下面這個例子:

{provide: Class2, useExisting: Class2}

doesn’t result in an instance being created, but you can see this rather than an alias. If a constructor requests Class2, Angular DI looks for another provider for key Class2 and injects the instance from this Class2 provider. You can see useExisting like a reference to another provider or an alias.

當構造函數需要Class2時,Angular DI從另一個key為Class2的provider裡查找,取出對應的執行個體進行注入。

Injectable and Provider are 2 different things. The injectable is a class DI can create an instance of, or a provided value that might be passed to a constructor. A provider is an entry in a registry of providers that DI maintains and that allows to lookup up providers by key (key is the type of a constructor parameter, a string or an InjectToken). The provider also holds information about how to “create” the injectable value/instance. DI looks up a provider, the provider provides the value, and DI passes the value (instance of an injectable or a value provided as-is) to a constructor.

Injectable和Provider是兩個不同的概念。Injectable是一個class,Angular DI可以基于該class建立執行個體,或者DI可以提供一個值,能夠傳遞到constructor裡。DI内部維護了一個provider系統資料庫,該系統資料庫支援根據key查詢provider.

Key is the type of a constructor parameter, a string or an InjectToken)

key是構造函數的參數,一個字元串或者InjectToken. Provider有足夠的knowledge知道如何去建立一個value或者執行個體。

DI詢問provider,provider提供值,DI将值傳遞到構造函數裡。

If you register MyClass as provider, this is the short form of { provide: MyClass, useClass: MyValue } where provide: MyClass is the key a provider can be found with, and useClass: MyValue is a strategy passed to the provider that informs the provider what value it should provide for this key.

provide: MyClass是provider的key,Angular DI系統資料庫裡根據這個key找到provider.

useClass: MyValue, 一個傳遞給provider的strategy,告訴provider對于指定的key,應該提供何種value.

useClass: MyValue相當于"use new MyClass(…)"

useExisting: Foo

DI需要去查找key為Foo的provider,然後注入Foo provider提供的value.

看一些具體的例子。

UseExisting

Angular 依賴注入架構裡 useExisting 和 useClass 的使用場景

在注入ServiceOldS時,使用ServiceNewS這個provider提供的值。

是以,運作時,old和newService兩個執行個體指向的都是newService執行個體,都是ServiceNewS這個provider注入的執行個體:

Angular 依賴注入架構裡 useExisting 和 useClass 的使用場景
Angular 依賴注入架構裡 useExisting 和 useClass 的使用場景
Angular 依賴注入架構裡 useExisting 和 useClass 的使用場景
Angular 依賴注入架構裡 useExisting 和 useClass 的使用場景

The provide property holds the token that serves as the key for both locating a dependency value and configuring the injector.

别名提供者:useExisting

useExisting 提供了一個鍵,讓你可以把一個令牌映射成另一個令牌。實際上,第一個令牌就是第二個令牌所關聯的服務的别名,這樣就建立了通路同一個服務對象的兩種途徑。

{ provide: MinimalLogger, useExisting: LoggerService }

useExisting 的作用

你可以使用别名接口來窄化 API。下面的例子中使用别名就是為了這個目的。

想象 LoggerService 有個很大的 API 接口,遠超過現有的三個方法和一個屬性。你可能希望把 API 接口收窄到隻有兩個你确實需要的成員。在這個例子中,MinimalLogger類-接口,就這個 API 成功縮小到了隻有兩個成員:

// Class used as a "narrowing" interface that exposes a minimal logger

// Other members of the actual implementation are invisible

export abstract class MinimalLogger {

 abstract logs: string[];

 abstract logInfo: (msg: string) => void;

}

2

3

4

5

6

消費代碼:

@Component({

 selector: 'app-hero-of-the-month',

 templateUrl: './hero-of-the-month.component.html',

 // TODO: move this aliasing, `useExisting` provider to the AppModule

 providers: [{ provide: MinimalLogger, useExisting: LoggerService }]

})

export class HeroOfTheMonthComponent {

 logs: string[] = [];

 constructor(logger: MinimalLogger) {

   logger.logInfo('starting up');

 }

1=

HeroOfTheMonthComponent 構造函數的 logger 參數是一個 MinimalLogger 類型,在支援 TypeScript 感覺的編輯器裡,隻能看到它的兩個成員 logs 和 logInfo:

Angular 依賴注入架構裡 useExisting 和 useClass 的使用場景

繼續閱讀