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
Другие вопросы по тегам