在不同的令牌下提供相同的服务实例

Provide the same service instance under different tokens

我有 2 个接口:

export interface IUserService {
    ...
}

export interface IUserStorageService {
    ...
}

一个服务同时实现它们:

@Injectable()
export class UserService implements IUserService, IUserStorageService {
    ...
}

(这部分好像和问题无关,所以只是为了完整起见。我可以很容易地将接口转换为抽象classes,直接将它们用作令牌而不用额外的注入令牌。)
现在,由于 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:

中将这些注入令牌全局映射到单个服务 class
@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 是每个应用程序的一个实例。

我怎样才能做到这一点?

我有一个非常相似的需求:我为许多组件提供服务 - 该服务有一个 dispatchEvent 函数和一个 subscribeToEvents 函数。我希望明确只有管理组件可以使用 dispatchEvent(),因此服务 implements 两个抽象 类 (然后可以将它们用作令牌 - 这比注入令牌更清晰format) - 一个有 dispatchEvents,另一个有 subscribeToEvents

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

您可以使用 useExisting 键,请记住它表示 "use the existing token"

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