Repository navigation
How to inject method parameter #1540
Description
Activity
This question appears to be out of context. The primary role of a DI (Dependency Injection) container is to inject dependencies into a constructor rather than injecting parameters into arbitrary functions. It is highly likely that you're attempting to achieve a goal that this library was not designed for.
Hi @skalinkin well said, you're correct. I will add to your answer few more things to make sure it covers all the aspect of IoC in general as well as exclusively for Inversify, so the next one to ask about this can refer to this content.
Hi @imcm7
In the example provided, you are attempting to use
@inject() decoratoron a method parameter inside a method (not the constructor), which is not supported by InversifyJS and in my other DI systems. Inversify primarly focused on constructor-based injection and property injectionConstructor Injection
@injectable() class A { constructor(@inject("B") private b: B) {} } // Or class B { constructor(private c: C) {} }
Property Injection
@injectable() class A { @inject("B") private b: B; }
Why Method Parameter Injection Is Problematic:
- InversifyJS manage object lifecycles and dependency resolution at the class level, typically focusing on constructors or properties. Injecting into individual method parameters, particularly for arbitrary methods (not constructors), can lead to unpredictable behavior;
- Method calls might happen outside the framework's lifecycle control. There would be ambiguity in determining when and how these dependencies should be injected, particularly if the method is called multiple times with different arguments.
Another point that you have not asked but your code is trying to do is inject primitive types, and let me elaborate this a bit more for you:
Inject Primitive types
Injecting primitive types such as
@inject() test: stringis a less common practice in DI's compared to injecting objects, services, or class instances. I recognize that exists cases where primitive injection is necessary, for example when configuration specific values like API keys, settings, or constant are required in your use case.Inversify is so feature rich that also handles this use case, you can inject primitives in constructors or as properties as well, here is an example:
Via Constructor
import "reflect-metadata"; import { injectable, inject, Container } from "inversify"; const TYPES = { apiKey: Symbol.for("apiKey"), }; @injectable() class ApiService { constructor(@inject(TYPES.apiKey) private apiKey: string) {} fetchData() { console.log(`Fetching data using API key: ${this.apiKey}`); } } const container = new Container(); container.bind<ApiService>(ApiService).toSelf(); container.bind<string>(TYPES.apiKey).toConstantValue("my-secret-api-key"); const apiService = container.get(ApiService); apiService.fetchData();
Via property
@injectable() class ApiService { @inject(TYPES.apiKey) private apiKey!: string; fetchData() { console.log(`Fetching data using API key: ${this.apiKey}`); } }
With every super power comes some points that needs to be taken in consideration when using primitive injection.
Three majors issues I would highlight are:1 - The overhead, using the DI system for a simple primitive that don't need management or change dynamically
2 - Overuse, you may end managing a bunch of primitives, task become cumbersome
3 - Type safety, since TypeScript does not enforce strict typing on symbols and strings used as service identifiers, you could introduce mistyped identifiers or mismatches between bindings and injected values.I hope you have a clear understanding about your request now, next time try to explain a bit better your goals, use cases, so we can be more efficient on resolving the matter.
Regards
- locked and limited conversation to collaborators
on Oct 23, 2024
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
How to inject method parameter