Каковы условия использования useExisting
поставщика?
Это useExistingOrThrowIfThereIsNone
или useExistingOrCreateIfThereIsNone
? Можно ли каким-либо образом изменить это поведение в зависимости от наших потребностей? Если один из них не поддерживается, может ли эмулироваться неподдерживаемый?
Документация полностью неясна и просто дает пример, что useExisting
может повторно использовать экземпляр из useClass
.
В этом примере
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)
создается экземпляр для первого поставщика и вводится
Когда мы пишем {provide: A, useClass: B}
, Angular создаст карту между токеном A
и классом B
.
Когда мы пишем {provide: A, useExisting: B}
, Angular создаст карту между токеном A
и токеном B
.
Разница между этими картами:
Просто небольшое добавление/разъяснение к ответу @GünterZöchbauer.
На самом деле он используетExistingOrThrowIfThereIsNone, когда мы говорим о токенах. useExisting создает псевдоним для другого токена, а не экземпляра, поэтому должен быть маркером, указанным useExisting, иначе будет выбрано исключение. Но когда мы говорим о экземплярах, он будет работать до тех пор, пока последний токен в цепочках регистрируется экземпляр, поэтому в этом смысле используетсяExistingOrCreateIfThereIsNone.
Рассмотрим это:
// T = token, I = instance
providers: [
{provide: B, useClass: A}, // T[B] => I[A]
{provide: C, useExisting: A}] // T[C] => ??? - there no T[A] declared
...
constructor(private a: B) {} // works
...
constructor(private a: C) {} // throws an exception:
В этом случае второе объявление будет вызывать ошибку, потому что токен C ссылается на токен A, но нет токена. Объявлено где угодно, даже хотя в инжекторе есть класс класса A. Angular не будет пытаться создать экземпляр A для токена C или связать токен с существующим экземпляром. Я просто случайно подтвердил это в одном из моих проектов.:)
Следующие действия будут работать, хотя из-за причин, хорошо описанных в других ответах:
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", а для token B это "использовать существующий экземпляр A или создать новый, если он не существует".
useExisting
похоже на псевдоним другого провайдера.useClass
- это просто новый поставщик, который отображает запрошенный тип на фактический тип, а ключ - запрошенный тип.Service
единичным везде, кроме как просто предоставить его один раз в корневом компоненте. DI Angular2 поддерживает один экземпляр для каждого поставщика. Если вы предоставите его только один раз, будет только один экземпляр.