
從上圖能看出,所有注入的示例都通過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
在注入ServiceOldS時,使用ServiceNewS這個provider提供的值。
是以,運作時,old和newService兩個執行個體指向的都是newService執行個體,都是ServiceNewS這個provider注入的執行個體:
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: