2017-02-11 110 views
3

我需要動態配置一些Angular服務,具體取決於運行時切換。在AOT前幾天,我把它用下面的代碼工作:動態模塊/服務配置和AOT

@NgModule({ 
    imports: [HttpModule], 
    providers: [] 
}) 
export class MyModule { 
    static forRoot(config: MyConfiguration): ModuleWithProviders { 
    return { 
     ngModule: MyModule, 
     providers: [ 
     SomeService, 
     { 
      provide: SomeOtherService, 
      useFactory: (some: SomeService, http: Http) => { 
      switch (config.type) { 
       case 'cloud': 
       return new SomeOtherService(new SomethingSpecificForCloud()); 
       case 'server': 
       return new SomeOtherService(new SomethingSpecificForServer()); 
      } 
      }, 
      deps: [SomeService, Http] 
     }, 

     ] 
    }; 
    } 
} 

然後在我的AppModule我會導入此爲MyModule.forRoot(myConfig)

當我更新CLI和Angular時,不再進行編譯,因爲它不能被靜態分析。我明白爲什麼,但我仍不確定解決問題的正確方法是什麼。

我首先濫用了這個forRoot()方法嗎?如何編寫模塊,以便根據運行時切換器生成不同的服務?

回答

3

我發現了一種實現方法:通過提供者公開配置,然後注入到「靜態」工廠函數中。上面的代碼應該是這樣的:

// Necessary if MyConfiguration is an interface 
export const MY_CONFIG = new OpaqueToken('my.config'); 

// Static factory function 
export function someOtherServiceFactory(config: MyConfiguration,some: SomeService, http: Http) { 
    switch (config.type) { 
    case 'cloud': 
     return new SomeOtherService(new SomethingSpecificForCloud()); 
    case 'server': 
     return new SomeOtherService(new SomethingSpecificForServer()); 
    } 
} 

@NgModule({ 
    imports: [HttpModule], 
    providers: [] 
}) 
export class MyModule { 
    static forRoot(config: MyConfiguration): ModuleWithProviders { 
    return { 
     ngModule: MyModule, 
     providers: [ 
     SomeService, 
     { provide: MY_CONFIG, useValue: config }, 
     { 
      provide: SomeOtherService, 
      useFactory: someOtherServiceFactory, 
      deps: [MY_CONFIG, SomeService, Http] 
     }, 

     ] 
    }; 
    } 
} 

它的工作原理和所有,但我仍然會在明知這是否真的是一個不錯的主意很感興趣,或者如果我做什麼可怕的錯誤,應予以考慮一個完全不同的方法來解決這個問題。


我找到了另一種解決方案:

  1. 使用角CLI環境。
  2. 爲不同環境的不同實現或依賴項的服務創建抽象類/接口。
  3. 從每個環境文件中導出正確的類型(誰說它只能是普通的JS對象?)。
  4. 在模塊提供商定義中,從環境導入
  5. 在編譯時,CLI環境將使正確的事情得到鏈接。

更多信息和示例項目在my blog

+0

我認爲這是唯一的選擇。 1條評論:從v4開始,你應該使用'InjectionToken'而不是'OpaqueToken'。 – mat3e