5

今天我偶然发现了一些我认为不会引起麻烦的事情。在Java和Spring中,我可以声明两个实现给定接口的bean,而在另一个注入它们的类中,我只能使用接口;这实际上就是我喜欢IoC的原因:你并不需要知道你正在使用什么对象,只有它是kind角2可注射接口?

所以在我的小Angular2 /打字稿程序,我试图做同样的:

webapp.module.ts:

... 
import { WebAppConfigurationService } from './app/services/webapp.configuration.service'; 

@NgModule({ 
    ... 
    providers: [WebAppConfigurationService] 
}) 
export class AppModule { } 

tnsapp.module.ts:

... 
import { TnsConfigurationService } from './services/tns.configuration.service'; 

@NgModule({ 
    ... 
    providers: [TnsConfigurationService] 
}) 
export class AppModule { } 

这两个模块都使用不同的提供者:TnsConfigurationServiceWebAppConfigurationService

然而,这两个@Injectable服务实现相同的接口:

configuration.interface:

export interface IConfigurationService { 
    ... 
} 

最后,在我的组成部分之一,我用这些模块我发现一个提供注射你在开始:

import { IConfigurationService } from './configuration.interface'; 

export class HeroesService { 

    constructor(private configurationService: IConfigurationService) { } 
} 

我的期望是这最后一个组件注入了正确的服务,即使在第仪表只是明确界定界面。当然,我得到一个错误(“错误:无法解析所有参数给英雄服务”)

现在,我不期待一个简单的解决方案,因为它听起来像一个架构缺乏。但也许有人可以指出我的另一种设计?

+0

查看DI文档https://angular.io/docs/ts/latest/guide/dependency-injection.html#typescript-interfaces-aren-t-valid-tokens – yurzui

+0

@yurzui我喜欢它:“这不是Angular的错。“ :-)好吧,也许还有一个美丽的方式来做到这一点...我稍后会阅读这个'OpaqueToken' – Sebas

+0

OpaqueToken主要用于非类提供者(工厂和值)。 – estus

回答

6

为了提供者被注入,它应该被注册为提供者。没有IConfigurationService供应商。它不能是一个提供者,因为编译后的JS代码中不存在接口。

对本应该被用作提供者的令牌接口通常的做法是为抽象类:

abstract class ConfigurationService { ... } 

@Injectable() 
class WebAppConfigurationService extends ConfigurationService { ... } 

... 
providers: [{ provide: ConfigurationService, useClass: WebAppConfigurationService }] 
... 

这个配方通常由角2本身,例如使用abstract NgLocalization classconcrete NgLocaleLocalization implementation

+0

这看起来确实不错,明天早上我会通知你(UTC) – Sebas

+0

https://cdn.meme.am/cache/instances/folder556/64985556.jpg – Sebas

+0

这对于角度4/5还是最新的?来自其他支持DI的语言,比如Java,我觉得使用抽象类作为提供者是非常奇怪的。 –