TSyringe如何注入所有实现某接口或继承抽象类的类实例?
TSyringe 注入同接口所有实现类实例实现方案
你的需求完全可以实现,效果和Spring中@Autowired注入同类型Bean集合的能力一致。
前置注意点
- TypeScript 接口仅存在于编译阶段,编译后会被完全擦除,因此不能直接用接口作为依赖注入的Token,需要使用字符串、Symbol或者抽象类作为Token载体。
@injectable()装饰器不能修饰接口,仅能修饰实际存在的类,你示例中给接口加@injectable()是无效写法。- 你示例中的
console.out属于笔误,正确API是console.log。
实现步骤
1. 定义接口与统一Token
import { injectable, inject, container } from "tsyringe"; // 定义统一的注入Token,避免硬编码字符串冲突 export const I_SERVICE_TOKEN = Symbol("IService"); // 接口无需加@injectable export interface IService { foo(): void; }
2. 编写接口实现类
@injectable() export class Service1 implements IService { foo() { console.log("bar"); } } @injectable() export class Service2 implements IService { foo() { console.log("baz"); } }
3. 容器中注册同Token多实现
TSyringe 支持对同一个Token多次注册不同的实现,解析时会自动返回所有实现的实例数组:
// 多次注册同一个Token,绑定不同实现类 container.register(I_SERVICE_TOKEN, { useClass: Service1 }); container.register(I_SERVICE_TOKEN, { useClass: Service2 });
4. 注入使用
@injectable() export class CollectorService { constructor( @inject(I_SERVICE_TOKEN) private services: IService[] ) { // 遍历调用所有实现 services.forEach(s => s.foo()); } }
抽象类简化方案(可选)
如果你不想单独维护Token,可以直接用抽象类替代接口,抽象类编译后是真实存在的构造函数,可以直接作为Token使用:
// 抽象类直接作为Token @injectable() export abstract class AbsService { abstract foo(): void; } // 注册时直接用抽象类当Token container.register(AbsService, { useClass: Service1 }); container.register(AbsService, { useClass: Service2 }); // 注入 constructor(@inject(AbsService) private services: AbsService[]) {}
内容的提问来源于stack exchange,提问作者Aníbal Deboni Neto
相关产品推荐
相关产品推荐

