使用 AOT 的类型提供程序中的角度条件
Posted
技术标签:
【中文标题】使用 AOT 的类型提供程序中的角度条件【英文标题】:Angular condition in type provider with AOT 【发布时间】:2018-08-01 04:49:16 【问题描述】:我有一个使用 AOT 编译的 Angular 项目。我希望能够注册根据配置动态解析的ClassProvider
。我使用的简化代码是这样的:
const isMock = Math.random() > 0.5;
@NgModule(
// ...
providers: [
provide: MyServiceBase, useClass: (isMock) ? MyServiceMock : MyService ,
],
bootstrap: [AppComponent]
)
export class AppModule
问题是当我用 AOT 编译它时,我总是得到相同的服务。我希望在按 F5 时获得不同的服务(因为第一行的randomness
)。在没有 AOT 的情况下编译时,它的行为符合我的预期。
这是 github 上的完整代码示例:https://github.com/vdolek/angular-test/tree/aot-conditioned-provider-problem。它与 ng serve
和 ng serve --aot
的行为不同。
我怎样才能做到这一点?我知道我可以使用FactoryProvider
,但是我必须复制服务依赖项(FactoryProvider
上的工厂函数和 deps 属性的参数)。
【问题讨论】:
【参考方案1】:要实现您需求的动态特性,您需要通过useFactory
属性使用factory providers,。
我已经分叉了您的存储库,并修改了您的 app.module.ts 如下,以便在 AOT 中工作。
修改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
如果您的服务依赖于其他服务(很可能会),您可以使用 deps
参数传递所需的依赖关系。
假设MyServiceBase
依赖于两个服务,MyService1
和MyService2
...您的工厂函数将如下所示:
export let myServiceFactory = (service1:MyService1, service2:MyService2) =>
const isMock = Math.random() > 0.5;
return isMock ? new MyServiceMock(service1, service2) : new MyService(service1, service2);
;
您的提供者声明如下所示
providers: [
provide: MyServiceBase,
useFactory: myServiceFactory,
deps: [MyService1, MyService2]
,
]
This guide 包含有关在 Angular 中实现依赖注入的各种方法的更多详细信息。
【讨论】:
感谢您的回答。正如我在问题中提到的,我熟悉 FactoryProviders。但我不喜欢我需要列出三次依赖项(在实际服务中、在工厂签名中和在deps
属性中)。我想避免这种代码重复——这就是问题的目的。 deps
属性甚至不会在构建时进行静态检查,因此当有人更改服务的依赖项时,他必须知道更改 deps
属性。
我明白,我不得不承认,我错过了最后一句话(我的脑海里自动想到了那个解决方案)。据我所知,没有其他方法可以满足您的要求。
Angular 5 在使用 AOT 时减少了对工厂函数等语法的限制。【参考方案2】:
我认为正如@jeanpaul-a 所说,除了使用工厂之外,您别无选择。但是管理依赖关系可能不是很干净。但是您可以使用Injector。我会选择类似的东西:
@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));
您还可以将 MyServiceBase 设置为接口并使用InjectionToken。 您将找到一个工作示例 here(但不是您的班级名称)。
【讨论】:
感谢您的回答。这不是我 100% 的愿望。但至少每次依赖项发生变化时都会出现构建错误,因此人们知道需要更新工厂。 是的,我知道,但是你不能在 useClass 中使用函数调用,并且当使用 AOT 编译时,你的表达式将是静态的。所以如果你想要一些动态,你需要一个工厂以上是关于使用 AOT 的类型提供程序中的角度条件的主要内容,如果未能解决你的问题,请参考以下文章