在RC5之前我使用appref injector作为服务定位器,如下所示:
Startup.ts
bootstrap(...)
.then((appRef: any) => {
ServiceLocator.injector = appRef.injector;
});
ServiceLocator.ts
export class ServiceLocator {
static injector: Injector;
}
成分:
let myServiceInstance = <MyService>ServiceLocator.injector.get(MyService)
现在在bootstrapModule()中执行相同操作。然后()不起作用,因为组件似乎在promise之前开始执行。
有没有办法在组件加载之前存储注入器实例?
我不想使用构造函数注入,因为我在基础组件中使用了注入器,这是由许多组件派生的,我宁愿不将注入器注入所有组件。
答案 0 :(得分:31)
对于今天的TypeScript和Angular 5,在导入全局注入器时避免WARNING in Circular dependency detected
,首先声明一个帮助器,例如app-injector.ts
:
import {Injector} from '@angular/core';
/**
* Allows for retrieving singletons using `AppInjector.get(MyService)` (whereas
* `ReflectiveInjector.resolveAndCreate(MyService)` would create a new instance
* of the service).
*/
export let AppInjector: Injector;
/**
* Helper to set the exported {@link AppInjector}, needed as ES6 modules export
* immutable bindings (see http://2ality.com/2015/07/es6-module-exports.html) for
* which trying to make changes after using `import {AppInjector}` would throw:
* "TS2539: Cannot assign to 'AppInjector' because it is not a variable".
*/
export function setAppInjector(injector: Injector) {
if (AppInjector) {
// Should not happen
console.error('Programming error: AppInjector was already set');
}
else {
AppInjector = injector;
}
}
接下来,在AppModule
中,使用以下方式设置:
import {Injector} from '@angular/core';
import {setAppInjector} from './app-injector';
export class AppModule {
constructor(injector: Injector) {
setAppInjector(injector);
}
}
如果需要,请使用:
import {AppInjector} from './app-injector';
const myService = AppInjector.get(MyService);
答案 1 :(得分:8)
我设法使用手动增强功能来完成它。不要使用&#34; bootstrap: [AppComponent]
&#34; @NgModule
中的声明,请改用ngDoBootstrap
方法:
export class AppModule {
constructor(private injector: Injector) {
}
ngDoBootstrap(applicationRef: ApplicationRef) {
ServiceLocator.injector = this.injector;
applicationRef.bootstrap(AppComponent);
}
}
答案 2 :(得分:3)
另一种角度为2.0.0的解决方案:
platformBrowserDynamic().bootstrapModule(AppModule, [
{
defaultEncapsulation: ViewEncapsulation.Emulated,
providers: [
{ provide: TRANSLATIONS, useValue: TRANSLATION },
{ provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
{ provide: LOCALE_ID, useValue: 'fr' }
]
}
]).then((modref: NgModuleRef<any>) => {
appInjector(modref.injector);
});
答案 3 :(得分:0)
基于类的解决方案。
通常,我需要从其他类使用的类中引用服务。 通过构造函数注入服务很麻烦,并且会导致不需要给定服务的调用类出现问题。
在Angular 8中,我设置了一个库类:ServiceInjectorModule (也可以在子模块内部使用)
(源自关于stackoverflow的类似答案)
文件:service-injector.module.ts
import { NgModule, Injector } from '@angular/core';
export let ServiceInjector: Injector;
@NgModule()
export class ServiceInjectorModule {
constructor(private injector: Injector) {
ServiceInjector = this.injector;
}
}
文件:my-lib.module.ts
注意:您可以跳过此库模块,因为只有在要使用其他服务或模块的情况下,这样做才更加方便。如果您跳过它,则将ServiceInjectorModule直接导入到您的AppModule中。
import { ServiceInjectorModule } from './service-injector.module';
const impExpModules = [
...,
ServiceInjectorModule,
...
];
@NgModule({
imports: [impExpModules],
exports: [impExpModules]
})
export class MyLibModule {}
将MyLibModule导入到您的AppModule或最合适的位置。
现在在您的组件或类中,只需:
import { ServiceInjector } from '../modules/lib/service-injector.module';
import { MyService } from '../services/my.service';
export class MyCurrentClass {
myService = ServiceInjector.get(MyService);
...
myLocalFunction() {
...
this.myService.myServiceFunction(...
}
}