2017-02-11 66 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