Могу ли я использовать собственные стратегии 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);
Другие вопросы по тегам