0
# Dependency Resolution and Injection
1
2
Core dependency injection functionality for retrieving instances, lazy injection, parameter passing, and component-based dependency access.
3
4
## Capabilities
5
6
### Core Dependency Resolution
7
8
Get instances from the Koin container with type safety and parameter injection.
9
10
```javascript { .api }
11
class Koin {
12
/**
13
* Get instance of type T from the container
14
* @param qualifier - Optional qualifier for specific instance
15
* @param parameters - Optional parameters for instance creation
16
* @returns Instance of type T
17
* @throws NoDefinitionFoundException if definition not found
18
*/
19
get<T>(qualifier?: Qualifier, parameters?: ParametersDefinition): T;
20
get<T>(clazz: any, qualifier?: Qualifier, parameters?: ParametersDefinition): T;
21
22
/**
23
* Get instance or null if not found - safe alternative to get()
24
* @param qualifier - Optional qualifier for specific instance
25
* @param parameters - Optional parameters for instance creation
26
* @returns Instance of type T or null if not found
27
*/
28
getOrNull<T>(qualifier?: Qualifier, parameters?: ParametersDefinition): T | null;
29
getOrNull<T>(clazz: any, qualifier?: Qualifier, parameters?: ParametersDefinition): T | null;
30
31
/**
32
* Lazy injection - resolved on first access
33
* @param qualifier - Optional qualifier for specific instance
34
* @param mode - Thread safety mode for lazy initialization (default: SYNCHRONIZED)
35
* @param parameters - Optional parameters for instance creation
36
* @returns Lazy<T> wrapper that resolves on first access
37
*/
38
inject<T>(
39
qualifier?: Qualifier,
40
mode?: LazyThreadSafetyMode,
41
parameters?: ParametersDefinition
42
): Lazy<T>;
43
44
/**
45
* Lazy injection that can return null if not found
46
* @param qualifier - Optional qualifier for specific instance
47
* @param mode - Thread safety mode for lazy initialization (default: SYNCHRONIZED)
48
* @param parameters - Optional parameters for instance creation
49
* @returns Lazy<T | null> wrapper that resolves on first access
50
*/
51
injectOrNull<T>(
52
qualifier?: Qualifier,
53
mode?: LazyThreadSafetyMode,
54
parameters?: ParametersDefinition
55
): Lazy<T | null>;
56
57
/**
58
* Get all instances of type T from the container
59
* @returns Array of all instances matching type T
60
*/
61
getAll<T>(): T[];
62
63
/**
64
* Declare existing instance in container for injection
65
* @param instance - Instance to declare
66
* @param qualifier - Optional qualifier for identification
67
* @param secondaryTypes - Additional types to bind
68
* @param allowOverride - Whether to allow overriding existing definition
69
*/
70
declare<T>(
71
instance: T,
72
qualifier?: Qualifier,
73
secondaryTypes?: any[],
74
allowOverride?: boolean
75
): void;
76
}
77
```
78
79
**Usage Examples:**
80
81
```javascript
82
import { startKoin, module } from "koin-core";
83
84
// Setup
85
const appModule = module((builder) => {
86
builder.single(() => new DatabaseService("localhost:5432"));
87
builder.factory(() => new ApiClient());
88
builder.single("cache", () => new CacheService());
89
});
90
91
startKoin((app) => app.modules([appModule]));
92
93
// Get Koin instance
94
const koin = GlobalContext.get();
95
96
// Basic instance retrieval
97
const database = koin.get(); // DatabaseService
98
const apiClient = koin.get(); // ApiClient (new instance each time)
99
100
// Qualified instance retrieval
101
const cache = koin.get("cache"); // CacheService
102
103
// Safe retrieval
104
const optionalService = koin.getOrNull(); // Service | null
105
106
// With parameters
107
const userService = koin.get(null, () => parametersOf("user123", true));
108
109
// Get all instances of a type
110
const allHandlers = koin.getAll(); // MessageHandler[]
111
112
// Declare runtime instance
113
const runtimeService = new RuntimeService();
114
koin.declare(runtimeService, "runtime");
115
```
116
117
### Component-Based Injection
118
119
Use the KoinComponent interface to add dependency injection capabilities to your classes.
120
121
```javascript { .api }
122
interface KoinComponent {
123
/**
124
* Get the Koin container instance
125
* @returns Koin container for dependency resolution
126
*/
127
getKoin(): Koin;
128
}
129
130
// Extension functions for KoinComponent
131
/**
132
* Get dependency instance from component
133
* @param qualifier - Optional qualifier for specific instance
134
* @param parameters - Optional parameters for instance creation
135
* @returns Instance of type T
136
*/
137
function get<T>(
138
this: KoinComponent,
139
qualifier?: Qualifier,
140
parameters?: () => ParametersHolder
141
): T;
142
143
/**
144
* Lazy dependency injection for component
145
* @param qualifier - Optional qualifier for specific instance
146
* @param mode - Thread safety mode for lazy initialization
147
* @param parameters - Optional parameters for instance creation
148
* @returns Lazy<T> wrapper that resolves on first access
149
*/
150
function inject<T>(
151
this: KoinComponent,
152
qualifier?: Qualifier,
153
mode?: LazyThreadSafetyMode,
154
parameters?: () => ParametersHolder
155
): Lazy<T>;
156
```
157
158
**Usage Examples:**
159
160
```javascript
161
import { KoinComponent } from "koin-core";
162
163
class UserController extends KoinComponent {
164
constructor() {
165
super();
166
// Direct injection
167
this.userService = this.get(); // UserService
168
this.logger = this.get("console"); // ConsoleLogger
169
170
// Lazy injection - resolved on first access
171
this.cacheLazy = this.inject(); // Lazy<CacheService>
172
this.apiClientLazy = this.inject("external"); // Lazy<ExternalApiClient>
173
}
174
175
async getUser(id) {
176
// Access lazy dependencies
177
const cache = this.cacheLazy.value;
178
const apiClient = this.apiClientLazy.value;
179
180
// Use injected dependencies
181
this.logger.info(`Getting user ${id}`);
182
return await this.userService.findById(id);
183
}
184
}
185
186
// Alternative implementation using composition
187
class ProductService {
188
constructor() {
189
this.koinComponent = new KoinComponent();
190
this.database = this.koinComponent.get(); // DatabaseService
191
this.validator = this.koinComponent.get("product"); // ProductValidator
192
}
193
}
194
```
195
196
### Property Injection
197
198
Inject configuration properties and runtime values.
199
200
```javascript { .api }
201
class Koin {
202
/**
203
* Get property value by key
204
* @param key - Property key
205
* @param defaultValue - Default value if property not found
206
* @returns Property value of type T
207
*/
208
getProperty<T>(key: string, defaultValue?: T): T;
209
210
/**
211
* Get property value or null if not found
212
* @param key - Property key
213
* @returns Property value or null
214
*/
215
getPropertyOrNull<T>(key: string): T | null;
216
217
/**
218
* Set property value
219
* @param key - Property key
220
* @param value - Property value
221
*/
222
setProperty(key: string, value: any): void;
223
224
/**
225
* Delete property by key
226
* @param key - Property key
227
*/
228
deleteProperty(key: string): void;
229
}
230
231
// Extension functions for KoinComponent
232
/**
233
* Get property from component context
234
* @param key - Property key
235
* @param defaultValue - Default value if property not found
236
* @returns Property value
237
*/
238
function getProperty<T>(
239
this: KoinComponent,
240
key: string,
241
defaultValue?: T
242
): T;
243
```
244
245
**Usage Examples:**
246
247
```javascript
248
import { startKoin, module, KoinComponent } from "koin-core";
249
250
// Setup with properties
251
startKoin((app) => {
252
app.modules([appModule]);
253
app.properties(new Map([
254
["database.url", "mongodb://localhost:27017"],
255
["api.timeout", 5000],
256
["debug.enabled", true]
257
]));
258
});
259
260
class DatabaseService extends KoinComponent {
261
constructor() {
262
super();
263
// Inject properties with defaults
264
this.url = this.getProperty("database.url", "mongodb://localhost:27017");
265
this.timeout = this.getProperty("api.timeout", 3000);
266
this.debugEnabled = this.getProperty("debug.enabled", false);
267
}
268
}
269
270
// Direct property access
271
const koin = GlobalContext.get();
272
const apiUrl = koin.getProperty("api.url", "https://api.default.com");
273
const debugMode = koin.getPropertyOrNull("debug.mode"); // boolean | null
274
275
// Runtime property updates
276
koin.setProperty("cache.ttl", 300);
277
koin.deleteProperty("temp.flag");
278
```
279
280
### Parameter-Based Injection
281
282
Pass parameters during dependency resolution for dynamic instance creation.
283
284
```javascript { .api }
285
/**
286
* Create parameters holder for injection
287
* @param parameters - Parameter values in order
288
* @returns ParametersHolder with indexed access
289
*/
290
function parametersOf(...parameters: any[]): ParametersHolder;
291
292
/**
293
* Create indexed parameter array
294
* @param parameters - Parameter values
295
* @returns ParametersHolder with array-like access
296
*/
297
function parameterArrayOf(...parameters: any[]): ParametersHolder;
298
299
/**
300
* Create parameter set for type-based access
301
* @param parameters - Parameter values
302
* @returns ParametersHolder with type-based access
303
*/
304
function parameterSetOf(...parameters: any[]): ParametersHolder;
305
306
/**
307
* Create empty parameters holder
308
* @returns Empty ParametersHolder
309
*/
310
function emptyParametersHolder(): ParametersHolder;
311
312
class ParametersHolder {
313
/**
314
* Get parameter by index and expected type
315
* @param index - Parameter index
316
* @param clazz - Expected parameter type
317
* @returns Parameter value of type T
318
*/
319
elementAt<T>(index: number, clazz?: new (...args: any[]) => T): T;
320
321
/**
322
* Get parameter by type (first matching type)
323
* @returns Parameter value of type T
324
*/
325
get<T>(): T;
326
327
/**
328
* Check if parameters are empty
329
* @returns true if no parameters
330
*/
331
isEmpty(): boolean;
332
333
/**
334
* Check if parameters exist
335
* @returns true if parameters exist
336
*/
337
isNotEmpty(): boolean;
338
339
/**
340
* Get parameter count
341
* @returns Number of parameters
342
*/
343
size(): number;
344
345
/**
346
* Destructuring support - get first parameter
347
* @returns First parameter
348
*/
349
component1<T>(): T;
350
351
/**
352
* Destructuring support - get second parameter
353
* @returns Second parameter
354
*/
355
component2<T>(): T;
356
357
/**
358
* Destructuring support - get third parameter
359
* @returns Third parameter
360
*/
361
component3<T>(): T;
362
363
/**
364
* Destructuring support - get fourth parameter
365
* @returns Fourth parameter
366
*/
367
component4<T>(): T;
368
369
/**
370
* Destructuring support - get fifth parameter
371
* @returns Fifth parameter
372
*/
373
component5<T>(): T;
374
}
375
```
376
377
**Usage Examples:**
378
379
```javascript
380
import { module, parametersOf, KoinComponent } from "koin-core";
381
382
// Module with parameter-accepting definitions
383
const userModule = module((builder) => {
384
builder.factory((scope, params) => {
385
const userId = params.get(); // string
386
const includeProfile = params.elementAt(1); // boolean
387
return new UserService(userId, includeProfile);
388
});
389
390
builder.single((scope, params) => {
391
const [host, port, database] = params.component1(), params.component2(), params.component3();
392
return new DatabaseConnection(host, port, database);
393
});
394
});
395
396
class UserController extends KoinComponent {
397
async getUser(userId, includeProfile = false) {
398
// Pass parameters during injection
399
const userService = this.get(null, () =>
400
parametersOf(userId, includeProfile)
401
);
402
403
return await userService.getUser();
404
}
405
406
async connectToDatabase() {
407
// Multiple parameters
408
const dbConnection = this.get(null, () =>
409
parametersOf("localhost", 5432, "myapp")
410
);
411
412
return dbConnection.connect();
413
}
414
}
415
416
// Different parameter creation methods
417
const indexedParams = parametersOf("value1", 42, true);
418
const arrayParams = parameterArrayOf("item1", "item2", "item3");
419
const setParams = parameterSetOf(new Date(), "config", 100);
420
const emptyParams = emptyParametersHolder();
421
```
422
423
### Lazy Injection
424
425
Defer dependency resolution until first access for performance optimization.
426
427
```javascript { .api }
428
interface Lazy<T> {
429
/**
430
* Get the lazily resolved value - resolved on first access
431
*/
432
value: T;
433
}
434
435
/**
436
* Thread safety modes for lazy initialization
437
*/
438
enum LazyThreadSafetyMode {
439
/** Thread-safe lazy initialization */
440
SYNCHRONIZED = "SYNCHRONIZED",
441
/** Not thread-safe but faster */
442
NONE = "NONE",
443
/** Thread-safe with publication safety */
444
PUBLICATION = "PUBLICATION"
445
}
446
```
447
448
**Usage Examples:**
449
450
```javascript
451
import { KoinComponent, LazyThreadSafetyMode } from "koin-core";
452
453
class ApplicationService extends KoinComponent {
454
constructor() {
455
super();
456
457
// Lazy dependencies - resolved on first access
458
this.expensiveService = this.inject(); // Lazy<ExpensiveService>
459
this.cacheService = this.inject("redis"); // Lazy<RedisCache>
460
461
// Thread-safe lazy with specific mode
462
this.sharedResource = this.inject(
463
"shared",
464
LazyThreadSafetyMode.SYNCHRONIZED
465
); // Lazy<SharedResource>
466
}
467
468
async processData(data) {
469
// Services are created only when first accessed
470
const expensive = this.expensiveService.value; // Created here if not already
471
const cache = this.cacheService.value; // Created here if not already
472
473
// Subsequent access uses cached instance
474
const cachedResult = this.cacheService.value.get("result");
475
476
return await expensive.process(data);
477
}
478
}
479
480
// Manual lazy injection
481
const koin = GlobalContext.get();
482
const lazyLogger = koin.inject("file"); // Lazy<FileLogger>
483
484
// Access when needed
485
function logMessage(message) {
486
const logger = lazyLogger.value; // Created on first access
487
logger.log(message);
488
}
489
```
490
491
## Types
492
493
```javascript { .api }
494
/** Function type for parameter definitions */
495
type ParametersDefinition = () => ParametersHolder;
496
497
/** Thread safety modes for lazy initialization */
498
enum LazyThreadSafetyMode {
499
SYNCHRONIZED = "SYNCHRONIZED",
500
NONE = "NONE",
501
PUBLICATION = "PUBLICATION"
502
}
503
504
/** Lazy wrapper interface */
505
interface Lazy<T> {
506
value: T;
507
}
508
509
/** Exception thrown when definition is not found */
510
class NoDefinitionFoundException extends Error {
511
constructor(message: string);
512
}
513
514
/** Exception thrown when instance creation fails */
515
class InstanceCreationException extends Error {
516
constructor(message: string, cause?: Error);
517
}
518
519
/** Exception thrown when required parameter is not found */
520
class NoParameterFoundException extends Error {
521
constructor(message: string);
522
}
523
```