Inversify如何实现部分属性注入?编译期已知参数值场景
针对Inversify多实例创建的替代方案
好问题!除了直接定义两个独立绑定之外,还有几种更灵活的方式来处理这种编译期已知参数值的实例创建需求,下面给你详细拆解:
1. 命名绑定(Named Bindings)
这是Inversify中处理同类型多实例最常用的方式之一,通过给绑定添加名称标识,注入时指定对应名称即可获取目标实例。
绑定代码示例:
// 绑定b为"a"的实例 container.bind<MyClass>(MyClass) .toDynamicValue((context) => { // 从容器中获取依赖的externalA const externalA = context.container.get<ExternalClassA>(EXTERNAL_A); return new MyClass(externalA, "a"); }) .whenTargetNamed("instance-with-b-a"); // 绑定b为"b"的实例 container.bind<MyClass>(MyClass) .toDynamicValue((context) => { const externalA = context.container.get<ExternalClassA>(EXTERNAL_A); return new MyClass(externalA, "b"); }) .whenTargetNamed("instance-with-b-b");
注入代码示例:
class OtherClass { constructor( @inject(MyClass) @named("instance-with-b-a") private instanceA: MyClass, @inject(MyClass) @named("instance-with-b-b") private instanceB: MyClass ) {} }
2. 标签绑定(Tagged Bindings)
和命名绑定逻辑类似,但标签支持自定义键值对,适合需要更丰富标识的场景(比如除了b值还想附加其他属性)。
绑定代码示例:
container.bind<MyClass>(MyClass) .toDynamicValue((context) => { const externalA = context.container.get<ExternalClassA>(EXTERNAL_A); return new MyClass(externalA, "a"); }) .whenTargetTagged("bValue", "a"); container.bind<MyClass>(MyClass) .toDynamicValue((context) => { const externalA = context.container.get<ExternalClassA>(EXTERNAL_A); return new MyClass(externalA, "b"); }) .whenTargetTagged("bValue", "b");
注入代码示例:
class OtherClass { constructor( @inject(MyClass) @tagged("bValue", "a") private instanceA: MyClass, @inject(MyClass) @tagged("bValue", "b") private instanceB: MyClass ) {} }
3. 工厂函数绑定(Factory Bindings)
如果未来可能需要扩展更多b的取值,工厂模式会更具扩展性——不用每次新增实例都加绑定,而是通过工厂动态生成。
第一步:定义工厂类型
// 定义工厂类型,接收b值返回MyClass实例 type MyClassFactory = (bValue: string) => MyClass; // 定义工厂的标识符号(建议统一管理) const TYPES = { MyClassFactory: Symbol.for("MyClassFactory") };
第二步:绑定工厂
container.bind<MyClassFactory>(TYPES.MyClassFactory) .toFactory<MyClass>((context) => { // 工厂函数内部从容器获取依赖,生成对应实例 return (bValue: string) => { const externalA = context.container.get<ExternalClassA>(EXTERNAL_A); return new MyClass(externalA, bValue); }; });
第三步:注入工厂并使用
class OtherClass { private instanceA: MyClass; private instanceB: MyClass; constructor(@inject(TYPES.MyClassFactory) myClassFactory: MyClassFactory) { // 直接通过工厂生成需要的实例 this.instanceA = myClassFactory("a"); this.instanceB = myClassFactory("b"); } }
方案选择建议
- 如果
b的取值固定且数量少(比如只有你说的"a"和"b"),命名/标签绑定足够简洁直观,代码可读性高; - 如果未来可能新增更多
b的取值,或者需要动态生成实例,工厂函数是更优选择,减少重复绑定代码。
内容的提问来源于stack exchange,提问作者Artsiom Miksiuk
相关产品推荐
相关产品推荐

