Can I use custom ReflectiveInjector strategies to get component providers?

半世苍凉 提交于 2019-11-28 08:57:12

问题


As you all know we have different strategies for providers: useClass, useExisting, useFactory, useValue. But what if I would like to add own strategy? Something like:

providers: [ { MyService: MyService, useAsyncFactory: MyAsyncFactory} ]

What is the best way to extend ReflectiveInjector and make Angular use your extended variant? I found the place where it's defined, but still looking for a way to overwrite existing Angular DI mechanism.


P.S.: Please don't ask why I need it and why not to use existing strategies. I'm doing research about Angular DI and the answer will help me to understand it better.


回答1:


Under the hood Angular doesn't use ReflectiveInjector to retrieve component providers so even if you manage to extend ReflectiveInjector it will have no effect on the component providers. You can see it here:

 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;
          }

The method is called when component requests a dependency, for example ViewContainerRef:

class MyComponent {
   constructor(vc: ViewContainerRef)

And this line:

const providerData = asProviderData(view, providerDef.index);

shows that dependency is retrieved from the view node, not a reflective injector. So when you do like this:

constructor(i: Injector) {
   console.log(i instanceOf ReflectiveInjector); // false
}

you will see that it's not real. It's just a wrapper around resolveDep function which encloses over the view and relevant view node.

Reflective injector is still used for the host view injectors. This is the injector that you pass when you instantiate a component dynamically:

componentFactory.create(hostViewInjector)

Here is the relevant code:

const value = startView.root.injector.get(depDef.token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR);

And also the module injector is consulted if you the dependency cannot be resolved on the component or the host view injector.
Here is the relevant code:

return startView.root.ngModule.injector.get(depDef.token, notFoundValue);


来源:https://stackoverflow.com/questions/45161602/can-i-use-custom-reflectiveinjector-strategies-to-get-component-providers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!