Могу ли я использовать собственные стратегии ReflectiveInjector для получения поставщиков компонентов?
Как вы все знаете, у нас разные стратегии для провайдеров: useClass
, useExisting
, useFactory
, useValue
, Но что, если я хотел бы добавить собственную стратегию? Что-то вроде:
providers: [ { MyService: MyService, useAsyncFactory: MyAsyncFactory} ]
Каков наилучший способ расширить ReflectiveInjector и сделать Angular своим расширенным вариантом? Я нашел место, где он определен, но все еще искал способ переписать существующий механизм Angular DI.
PS: Пожалуйста, не спрашивайте, зачем мне это нужно и почему нельзя использовать существующие стратегии. Я занимаюсь исследованием Angular DI, и ответ поможет мне лучше понять его.
1 ответ
Под капотом угловой не использовать ReflectiveInjector
извлекать поставщиков компонентов, поэтому даже если вам удастся расширить ReflectiveInjector, это не повлияет на поставщиков компонентов. Вы можете увидеть это здесь:
function resolveDep(...) {
...
default:
const providerDef =
(allowPrivateServices ? elDef.element !.allProviders :
elDef.element !.publicProviders) ![tokenKey];
if (providerDef) {
const providerData = asProviderData(view, providerDef.index);
^^^^^^^^^^^^^^^
if (providerData.instance === NOT_CREATED) {
providerData.instance = _createProviderInstance(view, providerDef);
}
return providerData.instance;
}
Метод вызывается, когда компонент запрашивает зависимость, например ViewContainerRef
:
class MyComponent {
constructor(vc: ViewContainerRef)
И эта строка:
const providerData = asProviderData(view, providerDef.index);
показывает, что зависимость извлекается из узла представления, а не отражающего инжектора. Итак, когда вы делаете так:
constructor(i: Injector) {
console.log(i instanceOf ReflectiveInjector); // false
}
вы увидите, что это не реально. Это просто обертка вокруг resolveDep
функция, которая охватывает вид и соответствующий узел вида.
Отражающая форсунка все еще используется для форсунок в виде узла. Это инжектор, который вы передаете, когда создаете экземпляр компонента динамически:
componentFactory.create(hostViewInjector)
Вот соответствующий код:
const value = startView.root.injector.get(depDef.token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR);
Кроме того, к инжектору модуля обращаются, если вы не можете разрешить зависимость от компонента или инжектора представления хоста.
Вот соответствующий код:
return startView.root.ngModule.injector.get(depDef.token, notFoundValue);