Angular2在运行时将AppModule中的服务注入到依赖的ngmodule的组件中

Angular2 inject a service from AppModule into dependent NgModule's component at runtime?

本文关键字:依赖 ngmodule 组件 注入 Angular2 运行时 AppModule 服务      更新时间:2023-09-26

如果我有:

AppModule imports: [SubModule], providers: [AppProvidedService]

SubModule declarations: [SubComponent]

SubComponent constructor(appProvidedService: AppProvidedService){}

:

Uncaught Can't resolve all parameters for SubComponent: (?).

基本上,它是在说AppProvidedService不能被注入器解析。

如何构建一个NgModule,让它依赖于另一个NgModule中创建的服务,而这个服务又依赖于它?

我尝试使用OpaqueToken和接口,但我仍然有同样的问题。子模块无法看到来自父模块的内容。

最终的愿望是拥有一个可以从导入它的应用程序中接受注入的模块。这样,我就可以把特定于应用程序的行为注入到公共组件中。

我明白了。它需要OpaqueTokens。

首先,为该接口提供一个接口和OpaqueToken (app- provisied .service.interface:

)
import { OpaqueToken } from "@angular/core";
export interface AppProvidedServiceInterface {
    ...
}
export const SERVICE_INTERFACE = new OpaqueToken("AppProvidedServiceInterface");

在AppModule的providers中:

    /*
     * 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中获取应用注入器的引用并存储它…(我们使用一个简单的单例类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);
}

现在,你的子模块有一个接口的引用,而不是一个具体的实现,AppModule可以通过providers: []注入所需的行为!

AppInjector单:

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