简体   繁体   English

具有AOT的类型提供者中的角度条件

[英]Angular condition in type provider with AOT

I have an Angular project which I compile with AOT. 我有一个Angular项目,我用AOT编译。 I want to be able to register ClassProvider that is resolved dynamically according to configuration. 我希望能够注册根据配置动态解析的ClassProvider Simplified code I use is this: 我使用的简化代码是这样的:

const isMock = Math.random() > 0.5;

@NgModule({
  // ...
  providers: [
    { provide: MyServiceBase, useClass: (isMock) ? MyServiceMock : MyService },
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

The problem is when I compile this with AOT I always get the same service. 问题是当我用AOT编译它时,我总是得到相同的服务。 I would expect to get different service while hitting F5 (because of the randomness on the first line). 我期望在击中F5时获得不同的服务(因为第一行的randomness )。 When compiling without AOT it behaves as I expect. 在没有AOT的情况下编译时,它的行为与我期望的一样。

Here is the whole code example on github: https://github.com/vdolek/angular-test/tree/aot-conditioned-provider-problem . 以下是github上的完整代码示例: https//github.com/vdolek/angular-test/tree/aot-conditioned-provider-problem It behaves differently with ng serve and ng serve --aot . 它与ng serveng serve --aot行为不同 - ng serve --aot

How can I achieve this? 我怎样才能做到这一点? I know I could use FactoryProvider , but then I would have to duplicate the services dependencies (parameters of the factory function and deps property on the FactoryProvider ). 我知道我可以使用FactoryProvider ,但我会重复的服务依存关系(工厂函数的参数和对财产的DEP FactoryProvider )。

To achieve the dynamic nature of your requirement, you need to use factory providers, via the useFactory attribute. 要实现需求的动态特性,您需要通过useFactory属性使用工厂提供程序

I've forked your repository, and amended your app.module.ts as follows, to work in AOT. 我已经分叉了您的存储库, 并按如下方式修改了您的app.module.ts ,以便在AOT中工作。

Amend app.module.ts as follows 修改app.module.ts如下

export let myServiceFactory = () => {

  const isMock = Math.random() > 0.5;

  return isMock ? new MyServiceMock() : new MyService();
}; 

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    {provide: MyServiceBase, useFactory: myServiceFactory},
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

In the case that your service is dependent on other services, which, most likely it will, you can use the deps argument, to pass on the required dependencies. 在您的服务依赖于其他服务的情况下,您可以使用deps参数来传递所需的依赖项。

Let's say that MyServiceBase is dependent on two services, MyService1 and MyService2 ... Your factory function will look as follows : 假设MyServiceBase依赖于两个服务MyService1MyService2 ......您的工厂函数将如下所示:

export let myServiceFactory = (service1:MyService1, service2:MyService2) => {

  const isMock = Math.random() > 0.5;

  return isMock ? new MyServiceMock(service1, service2) : new MyService(service1, service2);
}; 

and your providers decleration would look as follows 并且您的提供商的审核将如下所示

providers: [
    {
       provide: MyServiceBase, 
       useFactory: myServiceFactory,
       deps: [MyService1, MyService2]
    },
]

This guide contains further detail on the various ways of achieving dependency injection in Angular. 本指南包含有关在Angular中实现依赖项注入的各种方法的更多详细信息。

I think as @jeanpaul-a said you don't have any choice other than to use factory. 我认为@ jeanpaul-a说除了使用工厂之外别无选择。 But managing dependencies could be not very clean. 但是管理依赖关系可能不是很干净。 But what you could use is the Injector . 但你可以使用的是注射器 I'll go with something like: 我会用以下的东西:

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HelloComponent ],
  providers: [
    Dep1Service,
    Dep2Service,
    { provide: MyServiceBase, useFactory: createService, deps: [Injector] }
  ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

export function createService(injector: Injector) {
  const isMock = Math.random() > 0.5;
  if (mock) {
    return new MyService1(injector.get(Dep2Service));
  } else {
    return new MyService2(injector.get(Dep1Service));
  }
}

What you could also do is to set MyServiceBase as an interface and use InjectionToken . 你还可以做的是将MyServiceBase设置为接口并使用InjectionToken You will find a working example here (not your class name however). 你会在这里找到一个有效的例子(不过你的班级名称)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM