2016-09-14 48 views
2

如果我有:Angular2在運行時將AppModule中的服務注入到依賴的NgModule組件中?

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無法看到來自父模塊的內容。

最終的願望是擁有一個可以從導入它的應用程序注入的模塊。這樣,我可以將特定於應用程序的行爲注入到通用組件中。

+1

難道只是一個錯字?你正在使用'provide'而不是'providers'? –

+0

這種方法應該可行。我很少有這些問題轉向模塊方法,但能夠解決所有問題。不幸的是,我不記得如何))你需要把正確的地方放在正確的地方。是的,修正所有錯別字))) – rook

回答

0

我想通了。它確實需要OpaqueTokens。

首先,提供接口(APP-provided.service.interface接口和OpaqueToken:

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

而且在引導拿到參考應用注入器並將其存儲...(我們使用一個稱爲AppInjector的簡單單例類(源代碼在答案結尾處)):

platformBrowserDynamic().bootstrapModule(AppModule) 
.then((appRef: NgModuleRef<AppComponent>) => { 
     AppInjector.getInstance().setInjector(appRef.injector); 
    }, 
    error => console.log(error) // tslint:disable-line 
); 

然後,在你的子模塊,在你要使用的東西注入類,你必須得到使用注射器基礎上找到了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單:

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