【发布时间】:2018-03-03 00:12:14
【问题描述】:
我有 2 个接口:
export interface IUserService {
...
}
export interface IUserStorageService {
...
}
以及实现它们的单一服务:
@Injectable()
export class UserService implements IUserService, IUserStorageService {
...
}
(这部分似乎与问题无关,所以只是为了完整性。我可以很容易地将接口转换为抽象类,以直接将它们用作标记,而无需额外的注入标记。)
现在,由于 Angular 不支持将接口作为提供者的令牌,我必须创建注入令牌:
export let USER_SERVICE: InjectionToken<IUserService> = new InjectionToken<IUserService>("user.service");
export let USER_STORAGE_SERVICE: InjectionToken<IUserStorageService> = new InjectionToken<IUserStorageService>("user-storage.service");
现在我可以将这些注入令牌映射到我的app.module.ts 中的全局单一服务类:
@NgModule({
...
providers: [
{ provide: USER_SERVICE, useClass: UserService },
{ provide: USER_STORAGE_SERVICE, useClass: UserService }
],
...
})
export class AppModule {
...
}
最后,我现在可以将不同接口下的服务注入到我的组件中:
// Some component - sees service's API as IUserService
constructor(@Inject(USER_SERVICE) private readonly userService: IUserService) {
}
// Another component- sees service's API as IUserStorageService
constructor(@Inject(USER_STORAGE_SERVICE) private readonly userStorageService: IUserStorageService) {
}
这里的问题是 Angular 实际上创建了 2 个 UserService 实例,一个用于每个令牌,而我需要 UserService 成为每个应用程序的单个实例。
我怎样才能做到这一点?
【问题讨论】:
-
为什么甚至需要以两个不同的名称提供相同的服务?既然您无论如何都需要它是一个实例,那么是什么阻止您只提供一次呢?
-
@AakashJain:因为单个服务实现了 2 个接口,我的应用程序的不同组件需要使用其中任何一个接口与其通信。
-
我认为你过度设计了一些东西。但是你可以使用
{provide: USER_STORAGE_SERVICE, useExisting: USER_SERVICE}。 -
你所做的是绝对有效的。在使用扩展类时,它与强制转换函数参数完全相同。您限制对该函数中某些属性/方法的访问。此外,在未来的某个时候,您可以有不同的服务实现,因为您正在很好地利用抽象类/接口
-
我不认为这是过度设计!如果
IUserService和IUserStorageService由不同的类实现,那么IUserStorageService必须有许多setXYZ方法应该对IUserService“可见”,但对订阅XYZ: Observable<...>的组件不可见。于是我们又回到了最初的问题:如何让同一个类为应用程序的不同部分呈现不同的接口。
标签: angular typescript dependency-injection dependencies dependency-management