Angular如何区分匹配注入令牌?解析其与提供者的对应机制
核心问题
简而言之:Angular如何知晓传递给injector.get的注入令牌与某一提供者的注入令牌相对应?
根据Angular官方文档,InjectionToken可用于注入接口,示例如下:
const myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken'));
这会返回一个在其他地方已提供的实例,也就是说某处代码必须使用对应的注入令牌提供MyInterface的实现。
我的问题是:Angular如何确定传递给injector.get的上述注入令牌与提供者中提供的令牌相对应?
这似乎与new InjectionToken<MyInterface>('SomeToken')的组成部分有关,我们逐一分析可能的选项:
可排除:MyInterface类型参数
MyInterface可以直接排除,因为TypeScript接口会在编译过程中被完全擦除,没有任何运行时表示。InjectionToken文档也明确说明:
当你要注入的类型未被具体化(没有运行时表示)时,比如注入接口(...),请使用
InjectionToken
可排除:'SomeToken'描述字符串
也不是'SomeToken'这个字符串,因为文档中明确指出:
令牌的描述,仅用于调试目的,建议但不要求唯一
关于InjectionToken实例的误区
剩下的似乎只有InjectionToken实例了。那Angular会检查传递给injector.get的实例是否与提供者中的实例完全相同吗?看起来并非如此——因为示例里是新建了一个实例,提供者不可能持有同一个实例的引用。
正确匹配逻辑:共享同一个InjectionToken实例
你刚才的误区在于示例代码的写法——实际开发中绝对不会在injector.get里直接new InjectionToken,正确的做法是把InjectionToken实例定义为全局共享的常量:
// 定义共享的注入令牌 export const MY_INTERFACE_TOKEN = new InjectionToken<MyInterface>('SomeToken'); // 在提供者中使用这个令牌 providers: [ { provide: MY_INTERFACE_TOKEN, useClass: MyInterfaceImpl } ]; // 在获取实例时使用同一个令牌 const myInterface = injector.get(MY_INTERFACE_TOKEN);
Angular的注入系统是通过对象引用的严格相等性来匹配令牌的:只有当injector.get传入的令牌实例和提供者中provide字段指定的实例是同一个对象时,才会匹配到对应的提供者。
之前示例里直接new InjectionToken的写法只是为了演示类型参数用法,实际项目中必须保证令牌实例的唯一性和共享性,否则Angular无法找到对应的提供者。
内容的提问来源于stack exchange,提问作者F-H

