动态模块/服务配置和AOT

Kon*_*rus 7 angular2-aot angular

我需要动态配置一些Angular服务,具体取决于运行时切换.在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]
        },

      ]
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在我,AppModule我会导入这个MyModule.forRoot(myConfig).

当我更新CLI和Angular时,它不再编译,因为它无法进行静态分析.我理解为什么,但我仍然不确定解决它的正确方法是什么.

我是否forRoot()首先滥用这种方法?如何编写模块以便根据运行时开关生成不同的服务?

Kon*_*rus 7

我找到了一种方法来实现它:通过提供程序公开配置,然后注入"静态"工厂函数.上面的代码如下所示:

// 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]
        },

      ]
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

它是有效的,但我仍然非常有兴趣知道这是否真的是一个好主意,或者我是在做一些非常错误的事情,应该采取完全不同的方法来解决这个问题.


我找到了另一个解决方

  1. 使用Angular CLI环境.
  2. 为具有不同环境的不同实现或依赖关系的服务创建抽象类/接口.
  3. 从每个enviromnent文件中导出正确的类型(谁说它只是一个普通的JS对象?).
  4. 在模块提供程序定义中,从环境导入.
  5. 在编译时,CLI环境将使正确的事情得到链接.

我的博客上有更多信息和示例项目.