【问题标题】:Provide the same service instance under different tokens在不同的令牌下提供相同的服务实例
【发布时间】: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}
  • 你所做的是绝对有效的。在使用扩展类时,它与强制转换函数参数完全相同。您限制对该函数中某些属性/方法的访问。此外,在未来的某个时候,您可以有不同的服务实现,因为您正在很好地利用抽象类/接口
  • 我不认为这是过度设计!如果IUserServiceIUserStorageService 由不同的类实现,那么IUserStorageService 必须有许多setXYZ 方法应该对IUserService “可见”,但对订阅XYZ: Observable&lt;...&gt; 的组件不可见。于是我们又回到了最初的问题:如何让同一个类为应用程序的不同部分呈现不同的接口。

标签: angular typescript dependency-injection dependencies dependency-management


【解决方案1】:

我有一个非常相似的要求:我正在为许多组件提供服务——该服务有一个dispatchEvent 函数和一个subscribeToEvents 函数。我想明确一点,只有管理组件可以使用dispatchEvent(),所以服务implements 有两个抽象类(然后这些可以用作令牌——这比注入令牌格式更清晰)——一个有dispatchEvents,一个其他有 subscribeToEvents

providers: [
    {provide: AbstractSettingsManager, useClass: SettingsEventService},
    {provide: AbstractSettingsConsumer, useExisting: AbstractSettingsManager}
  ],

您可以使用useExisting 键,并记住它的意思是“使用现有令牌”

所有组件都将具有相同的 ServiceEventService 实例,但由于我提供了 AbstractSettingsManager/AbstractSettingsConsumer,组件将只能访问(通过 TypeScript 检查)一个或其他服务功能

【讨论】:

    猜你喜欢
    • 2018-12-31
    • 1970-01-01
    • 2012-08-17
    • 2018-01-04
    • 1970-01-01
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多