Angular 2 useExisting провайдеры
Каковы виды использования для useExisting
провайдер?
Это useExistingOrThrowIfThereIsNone
или же useExistingOrCreateIfThereIsNone
? Можно ли каким-то образом выбрать одно из этих способов поведения в зависимости от наших потребностей? Если один из них не поддерживается, можно ли эмулировать неподдерживаемый?
Документация совершенно неясна по этому поводу и просто приводит пример useExisting
может повторно использовать экземпляр из useClass
,
3 ответа
С этим примером
providers: [
A,
{provide: B, useClass: A},
{provide: C, useExisting: A}]
Если у вас есть
constructor(private a: A)
экземпляр для первого провайдера создан.
constructor(private b: B)
экземпляр для 2-го провайдера создан
constructor(private c: C)
экземпляр первого провайдера внедряется.
Если вы начинаете заново с
constructor(private c: C)
экземпляр для первого провайдера создан и внедрен
Небольшое дополнение / уточнение к ответу @GünterZöchbauer.
Это на самом деле useExistingOrThrowIfThereIsNone, когда мы говорим о токенах. 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 не будет пытаться создать экземпляр A для токена C или связать токен C с существующим экземпляром 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 это msgstr "использовать существующий экземпляр А или создать новый, если его нет".
Когда мы пишем {provide: A, useClass: B}
Angular создаст карту между токенами A
и класс B
,
Когда мы пишем {provide: A, useExisting: B}
Angular создаст карту между токенами A
и токен B
,
Разница между этими картами:
- токен A -> экземпляр класса B
- токен A -> токен B -> экземпляр некоторого класса для токена B