useExisting
提供商的用法是什么?
是useExistingOrThrowIfThereIsNone
还是useExistingOrCreateIfThereIsNone
?根据我们的需要,可以某种方式有目的地选择其中一种行为吗?如果其中一个不受支持,是否可以模拟不受支持的一个?
文档完全不清楚,只是举例说明useExisting
可以重用useClass
中的实例。
答案 0 :(得分:23)
使用此示例
providers: [
A,
{provide: B, useClass: A},
{provide: C, useExisting: A}]
如果你有
constructor(private a: A)
创建第一个提供者的实例。
constructor(private b: B)
创建第二个提供者的实例
constructor(private c: C)
注入第一个提供者的实例。
如果你重新开始
constructor(private c: C)
创建并注入第一个提供者的实例
答案 1 :(得分:4)
当我们写{provide: A, useClass: B}
时,Angular会在令牌 A
和类 B
之间创建地图。
当我们写{provide: A, useExisting: B}
时,Angular会在令牌 A
和令牌 B
之间创建地图。
这些地图之间的区别:
答案 2 :(得分:4)
对@GünterZöchbauer的答案进行简单的补充/澄清。
当我们谈论令牌时,它实际上是在使用ExistingOrThrowIfThereIsNone。 useExisting为另一个标记而不是实例创建别名,因此必须是useExisting引用的标记,否则将抛出异常。但是,当我们谈论实例时,只要链中的最后一个标记注册实例,它就会起作用,因此从这个意义上说它是useExistingOrCreateIfThereIsNone。
考虑一下:
// T = token, I = instance
providers: [
{provide: B, useClass: A}, // T[B] => I[A]
{provide: C, useExisting: A}] // T[C] => ??? - there's no T[A] declared
...
constructor(private a: B) {} // works
...
constructor(private a: C) {} // throws an exception:
在这种情况下,第二个声明会引发错误,因为令牌 C指的是令牌 A但是没有声明令牌 A,甚至虽然注射器中有A类的实例。 Angular不会尝试为令牌 C创建实例 A或将令牌 C与现有实例 A关联起来A.我只是在我的一个项目中意外地验证了它。 :)
由于其他答案中有充分描述的原因,以下内容将有效:
providers: [
{provide: B, useClass: A}, // T[B] => I[A]
{provide: C, useExisting: B}] // T[C] => T[B] => I[A]
...
constructor(private a: B) {} // works
...
constructor(private a: C) {} // works
在此示例中,即使没有为令牌创建的实例 A,也会为令牌 C创建A的实例 B.因此,对于令牌 C,“使用任何实例应为令牌 B”提供,并为令牌 B“使用现有的实例 A或创建新的,如果没有”。