如果我有:
AppModule
imports: [SubModule],
providers: [AppProvidedService]
和
SubModule
declarations: [SubComponent]
和
SubComponent
constructor(appProvidedService: AppProvidedService){}
我明白了:
Uncaught Can't resolve all parameters for SubComponent: (?).
基本上,它表示注射器无法解析AppProvidedService。
如何构建NgModule,使其依赖于依赖于它的NgModule中创建的服务?
我尝试使用OpaqueToken和接口,但我仍然遇到同样的问题。 SubModule无法看到来自父模块的内容。
最终的愿望是拥有一个可以从导入它的应用程序中注入的模块。这样,我可以将特定于应用程序的行为注入通用组件。
答案 0 :(得分:0)
我想出来了。它确实需要OpaqueTokens。
首先,为接口提供一个接口和OpaqueToken(app-provided.service.interface:
import { OpaqueToken } from "@angular/core";
export interface AppProvidedServiceInterface {
...
}
export const SERVICE_INTERFACE = new OpaqueToken("AppProvidedServiceInterface");
在AppModule的提供者中:
/*
* Injection of app-specific behavior into a common module without hard dependencies:
*
* This is how you inject a service into a module that is imported
* and prevent that module from having a hard dependency on the actual
* implementation. Use an interface with an OpaqueToken. Then the
* component that needs it imports it and uses the AppInjector to get the
* instance.
*/
{
provide: SERVICE_INTERFACE,
useFactory: () => {
return new AppProvidedService();
}
}
在bootstrap中获取对app注入器的引用并存储它...(我们使用一个名为AppInjector的简单单例类(答案结尾处的源代码)):
platformBrowserDynamic().bootstrapModule(AppModule)
.then((appRef: NgModuleRef<AppComponent>) => {
AppInjector.getInstance().setInjector(appRef.injector);
},
error => console.log(error) // tslint:disable-line
);
然后,在SubModule中,在要使用注入事物的类中,必须使用注入器根据OpaqueToken(sub.component.ts)查找类:
// DO NOT REFERENCE A CONCRETE SERVICE!
private appProvidedService: AppProvidedServiceInterface;
constructor(/* can't inject it here */) {
// Get the app-specific behavior from the service injected in the application module.
this.appProvidedService = AppInjector.getInstance().getInjector().get(SERVICE_INTERFACE);
}
现在,你的SubModule有一个对接口的引用,而不是具体的实现,AppModule可以通过providers: []
注入所需的行为!
AppInjector singleton:
import { Injector } from "@angular/core";
export class AppInjector {
private static instance: AppInjector;
private injector: Injector;
constructor() {
// throw new Error("Singleton - can't instantiate.");
}
public static getInstance() {
if (!AppInjector.instance) {
AppInjector.instance = new AppInjector();
}
return AppInjector.instance;
}
public setInjector(injector: Injector) {
this.injector = injector;
}
public getInjector(): Injector {
return this.injector;
}
}