Angular 带字符串标记的动态 DI

Angular dynamic DI with string token

似乎 Angular 6 (4+?) 需要令牌 objects 是唯一的才能使 DI 工作。然而,我想使用一个动态令牌,由模板 html 代码提供,这将允许我的新指令按名称.

解析服务

当前代码:

this.service = this.injector.get(new InjectionToken<IServiceRef>(tokenName));

失败:

Error: StaticInjectorError(AppModule)[InjectionToken the_token_name]: 

当我用旧的 depricated(在 angular 4 中)Injector.get 函数替换我的代码时,它工作正常,因为注入器比较名称(我确实在视图中提供服务那个名字……)。然而,使用新的 DI 我无法实现我想要的。

那么,如何应对呢?

您必须为您的令牌使用全局存储对象。我推荐你使用地图。

export const tokens: Map<string, InjectionToken<IServiceRef>> = new Map();
tokens.set('tokenName', new InjectionToken<IServiceRef>('tokenName'));

您必须使用地图对象来声明提供者。

@NgModule({
     providers: [
          {provide: tokens.get('tokenName'), useValue: new Service()}
     ]
 );

您现在可以通过字符串值查找令牌。

this.service = this.injector.get(tokens.get(the_token_name));

我不知道这在 Angular 6 中发生了变化,但我确实记得文档中说令牌是按值引用的。这意味着 DI 使用 === 来匹配依赖项。

如果您通过令牌名称进行匹配,您将在 DI 中遇到冲突。例如,许多库都声明了一个 "document" 标记。所以你不想使用字符串名称。因为碰撞很难找到和修复。