众所周知,我们为提供商制定了不同的策略:useClass
,useExisting
,useFactory
,useValue
。但是,如果我想添加自己的策略呢?类似的东西:
providers: [ { MyService: MyService, useAsyncFactory: MyAsyncFactory} ]
扩展ReflectiveInjector 以及让Angular使用扩展变体的最佳方法是什么?我发现the place已定义,但仍在寻找覆盖现有Angular DI机制的方法。
P.S。:请不要问我为什么需要它,为什么不使用现有的策略。我正在研究Angular DI,答案将帮助我更好地理解它。
答案 0 :(得分:3)
引擎盖下Angular不使用ReflectiveInjector
来检索组件提供程序,因此即使您设法扩展ReflectiveInjector,它也不会对组件提供程序产生影响。你可以看到它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;
}
当组件请求依赖项时调用该方法,例如ViewContainerRef
:
class MyComponent {
constructor(vc: ViewContainerRef)
这一行:
const providerData = asProviderData(view, providerDef.index);
表示从视图节点检索依赖关系,而不是反射注入器。所以当你这样做时:
constructor(i: Injector) {
console.log(i instanceOf ReflectiveInjector); // false
}
你会发现它并不真实。围绕视图和相关视图节点的resolveDep
函数周围的It's just a wrapper。
反射式注射器仍用于主视图注射器。这是您动态实例化组件时传递的注入器:
componentFactory.create(hostViewInjector)
Here is相关代码:
const value = startView.root.injector.get(depDef.token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR);
如果无法在组件或主机视图注入器上解析依赖关系,也会查询模块注入器。
Here is相关代码:
return startView.root.ngModule.injector.get(depDef.token, notFoundValue);