0
# Qualifiers & Parameters
1
2
Type-safe qualifier system for distinguishing between multiple instances of the same type, and parameter injection for runtime dependency configuration. Essential for complex dependency scenarios and runtime parameter passing.
3
4
## Capabilities
5
6
### Qualifier Interface
7
8
Base interface for creating type-safe qualifiers to distinguish between instances.
9
10
```kotlin { .api }
11
/**
12
* Base qualifier interface for distinguishing instances
13
*/
14
interface Qualifier {
15
/**
16
* String value of the qualifier
17
*/
18
val value: String
19
}
20
```
21
22
### String-Based Qualifiers
23
24
Create qualifiers using string values for simple naming scenarios.
25
26
```kotlin { .api }
27
/**
28
* Create string-based qualifier
29
* @param name - String identifier for the qualifier
30
* @return Qualifier instance
31
*/
32
fun named(name: String): Qualifier
33
34
/**
35
* Create enum-based qualifier
36
* @param name - Enum value for the qualifier
37
* @return Qualifier instance
38
*/
39
fun named(name: Enum<*>): Qualifier
40
41
/**
42
* Alternative string qualifier function
43
* @param name - String identifier for the qualifier
44
* @return Qualifier instance
45
*/
46
fun qualifier(name: String): Qualifier
47
48
/**
49
* Alternative enum qualifier function
50
* @param name - Enum value for the qualifier
51
* @return Qualifier instance
52
*/
53
fun qualifier(name: Enum<*>): Qualifier
54
55
/**
56
* Short form string qualifier
57
* @param name - String identifier for the qualifier
58
* @return Qualifier instance
59
*/
60
fun _q(name: String): Qualifier
61
```
62
63
**Usage Examples:**
64
65
```kotlin
66
import org.koin.core.qualifier.named
67
import org.koin.core.qualifier.qualifier
68
import org.koin.core.qualifier._q
69
import org.koin.dsl.module
70
71
enum class DatabaseType { PRIMARY, CACHE, ANALYTICS }
72
73
val qualifierModule = module {
74
// String qualifiers
75
single<Database>(named("primary")) { PostgreSQLDatabase() }
76
single<Database>(named("cache")) { RedisDatabase() }
77
single<Database>(qualifier("analytics")) { ClickHouseDatabase() }
78
79
// Enum qualifiers
80
single<ApiClient>(named(DatabaseType.PRIMARY)) { PrimaryApiClient() }
81
single<ApiClient>(named(DatabaseType.CACHE)) { CacheApiClient() }
82
83
// Short form qualifiers
84
single<Logger>(_q("file")) { FileLogger() }
85
single<Logger>(_q("console")) { ConsoleLogger() }
86
87
// Using qualifiers in dependencies
88
single<UserService> {
89
UserServiceImpl(
90
database = get(named("primary")),
91
cache = get(named("cache")),
92
logger = get(_q("file"))
93
)
94
}
95
}
96
97
// Usage in components
98
class DataService : KoinComponent {
99
private val primaryDb: Database by inject(named("primary"))
100
private val cacheDb: Database by inject(named("cache"))
101
private val analyticsDb: Database by inject(qualifier("analytics"))
102
103
fun processData() {
104
val data = primaryDb.query("SELECT * FROM users")
105
cacheDb.store("users", data)
106
analyticsDb.track("users_queried", data.size)
107
}
108
}
109
```
110
111
### Type-Based Qualifiers
112
113
Create qualifiers using type information for strongly-typed scenarios.
114
115
```kotlin { .api }
116
/**
117
* Create type-based qualifier using reified generics
118
* @return Type qualifier based on T
119
*/
120
inline fun <reified T> named(): Qualifier
121
122
/**
123
* Create type-based qualifier using reified generics
124
* @return Type qualifier based on T
125
*/
126
inline fun <reified T> qualifier(): Qualifier
127
128
/**
129
* Short form type-based qualifier
130
* @return Type qualifier based on T
131
*/
132
inline fun <reified T> _q(): Qualifier
133
134
/**
135
* Type-based qualifier implementation
136
* @param type - KClass representing the type
137
*/
138
class TypeQualifier(type: KClass<*>) : Qualifier
139
```
140
141
**Usage Examples:**
142
143
```kotlin
144
import org.koin.core.qualifier.named
145
import org.koin.core.qualifier.qualifier
146
import org.koin.core.qualifier._q
147
import org.koin.dsl.module
148
149
// Marker classes for type qualifiers
150
class PrimaryDatabase
151
class CacheDatabase
152
class AnalyticsDatabase
153
154
val typeQualifierModule = module {
155
// Type-based qualifiers
156
single<Database>(named<PrimaryDatabase>()) { PostgreSQLDatabase() }
157
single<Database>(qualifier<CacheDatabase>()) { RedisDatabase() }
158
single<Database>(_q<AnalyticsDatabase>()) { ClickHouseDatabase() }
159
160
// Scope qualifiers using types
161
scope(named<UserScope>()) {
162
scoped<UserService> { UserServiceImpl(get(named<PrimaryDatabase>())) }
163
scoped<UserCache> { UserCacheImpl(get(qualifier<CacheDatabase>())) }
164
}
165
}
166
167
// Usage with type safety
168
class AnalyticsService : KoinComponent {
169
private val analyticsDb: Database by inject(_q<AnalyticsDatabase>())
170
private val primaryDb: Database by inject(named<PrimaryDatabase>())
171
172
fun generateReport() {
173
val data = primaryDb.query("SELECT * FROM analytics")
174
val report = analyticsDb.process(data)
175
// Process report...
176
}
177
}
178
```
179
180
### Qualifier Implementations
181
182
Built-in qualifier implementations for different use cases.
183
184
```kotlin { .api }
185
/**
186
* String-based qualifier implementation
187
* @param value - String identifier
188
*/
189
data class StringQualifier(override val value: String) : Qualifier
190
191
/**
192
* Type-based qualifier implementation
193
* @param type - KClass representing the type
194
*/
195
class TypeQualifier(type: KClass<*>) : Qualifier {
196
override val value: String
197
}
198
199
typealias QualifierValue = String
200
```
201
202
**Usage Examples:**
203
204
```kotlin
205
import org.koin.core.qualifier.StringQualifier
206
import org.koin.core.qualifier.TypeQualifier
207
208
class CustomQualifierService : KoinComponent {
209
210
fun demonstrateQualifiers() {
211
// Create qualifiers programmatically
212
val stringQual = StringQualifier("custom")
213
val typeQual = TypeQualifier(String::class)
214
215
// Use in dependency resolution
216
val customService = get<MyService>(stringQual)
217
val typedService = get<MyService>(typeQual)
218
219
// Qualifier values are accessible
220
println("String qualifier: ${stringQual.value}")
221
println("Type qualifier: ${typeQual.value}")
222
}
223
}
224
```
225
226
### Parameter System
227
228
Runtime parameter injection for dynamic dependency configuration.
229
230
```kotlin { .api }
231
/**
232
* Parameter container for dependency injection
233
* @param values - Mutable list of parameter values
234
* @param useIndexedValues - Whether to use indexed parameter access
235
*/
236
class ParametersHolder(
237
private val values: MutableList<Any?> = mutableListOf(),
238
private val useIndexedValues: Boolean? = null
239
) {
240
/**
241
* Get parameter by index
242
* @param index - Parameter index
243
* @return Parameter value cast to T
244
*/
245
fun <T> get(index: Int): T
246
247
/**
248
* Get parameter by index with null safety
249
* @param index - Parameter index
250
* @return Parameter value cast to T or null
251
*/
252
fun <T> getOrNull(index: Int): T?
253
254
/**
255
* Set parameter at index
256
* @param index - Parameter index
257
* @param value - Parameter value
258
*/
259
fun <T> set(index: Int, value: T)
260
261
/**
262
* Get parameter at index (alias for get)
263
* @param index - Parameter index
264
* @return Parameter value cast to T
265
*/
266
fun <T> elementAt(index: Int): T
267
268
/**
269
* Get number of parameters
270
* @return Parameter count
271
*/
272
fun size(): Int
273
274
/**
275
* Check if parameters are empty
276
* @return True if no parameters
277
*/
278
fun isEmpty(): Boolean
279
280
/**
281
* Add parameter to end
282
* @param value - Parameter value
283
*/
284
fun add(value: Any?)
285
286
/**
287
* Insert parameter at index
288
* @param index - Target index
289
* @param value - Parameter value
290
*/
291
fun insert(index: Int, value: Any?)
292
293
// Component functions for destructuring
294
operator fun component1(): Any?
295
operator fun component2(): Any?
296
operator fun component3(): Any?
297
operator fun component4(): Any?
298
operator fun component5(): Any?
299
}
300
```
301
302
### Parameter Factory Functions
303
304
Create parameter holders using different patterns.
305
306
```kotlin { .api }
307
/**
308
* Create parameters from variable arguments
309
* @param values - Variable number of parameter values
310
* @return ParametersHolder with values
311
*/
312
fun parametersOf(vararg values: Any?): ParametersHolder
313
314
/**
315
* Create indexed parameters from array
316
* @param values - Array of parameter values
317
* @return ParametersHolder with indexed access
318
*/
319
fun parameterArrayOf(vararg values: Any?): ParametersHolder
320
321
/**
322
* Create parameters from set/collection
323
* @param values - Set of parameter values
324
* @return ParametersHolder with set-based values
325
*/
326
fun parameterSetOf(vararg values: Any?): ParametersHolder
327
328
/**
329
* Create empty parameter holder
330
* @return Empty ParametersHolder
331
*/
332
fun emptyParametersHolder(): ParametersHolder
333
```
334
335
**Usage Examples:**
336
337
```kotlin
338
import org.koin.core.parameter.parametersOf
339
import org.koin.core.parameter.parameterArrayOf
340
import org.koin.core.parameter.emptyParametersHolder
341
import org.koin.dsl.module
342
343
// Module with parameterized dependencies
344
val parameterModule = module {
345
factory<HttpClient> { params ->
346
val baseUrl = params.get<String>(0)
347
val timeout = params.get<Int>(1)
348
val retries = params.getOrNull<Int>(2) ?: 3
349
HttpClientImpl(baseUrl, timeout, retries)
350
}
351
352
factory<DatabaseConnection> { params ->
353
val (host, port, database, user, password) = params
354
DatabaseConnectionImpl(host as String, port as Int, database as String, user as String, password as String)
355
}
356
}
357
358
// Usage with parameters
359
class NetworkService : KoinComponent {
360
361
fun createClients() {
362
// Simple parameters
363
val apiClient = get<HttpClient> {
364
parametersOf("https://api.example.com", 30)
365
}
366
367
// Parameters with optional values
368
val clientWithRetries = get<HttpClient> {
369
parametersOf("https://api.example.com", 60, 5)
370
}
371
372
// Array parameters
373
val configuredClient = get<HttpClient> {
374
parameterArrayOf("https://secure-api.example.com", 45)
375
}
376
377
// Destructured parameters
378
val dbConnection = get<DatabaseConnection> {
379
parametersOf("localhost", 5432, "myapp", "user", "password")
380
}
381
382
// Empty parameters
383
val defaultService = get<DefaultService> { emptyParametersHolder() }
384
}
385
}
386
```
387
388
### Parameter Usage in Definitions
389
390
Use parameters within dependency definitions for dynamic configuration.
391
392
```kotlin { .api }
393
typealias ParametersDefinition = () -> ParametersHolder
394
```
395
396
**Usage Examples:**
397
398
```kotlin
399
import org.koin.dsl.module
400
import org.koin.core.parameter.parametersOf
401
402
val dynamicModule = module {
403
404
// Single with parameters
405
single<ApiService> { params ->
406
val baseUrl = params.get<String>(0)
407
val apiKey = params.getOrNull<String>(1) ?: "default-key"
408
ApiServiceImpl(baseUrl, apiKey)
409
}
410
411
// Factory with parameter validation
412
factory<UserValidator> { params ->
413
val rules = params.get<ValidationRules>(0)
414
val strict = params.getOrNull<Boolean>(1) ?: false
415
416
require(rules.isValid()) { "Invalid validation rules" }
417
UserValidatorImpl(rules, strict)
418
}
419
420
// Scoped with complex parameters
421
scope(named<SessionScope>()) {
422
scoped<SessionManager> { params ->
423
val userId = params.get<String>(0)
424
val permissions = params.get<Set<Permission>>(1)
425
val config = params.getOrNull<SessionConfig>(2) ?: SessionConfig.default()
426
427
SessionManagerImpl(userId, permissions, config)
428
}
429
}
430
}
431
432
// Advanced parameter usage
433
class ConfigurableService : KoinComponent {
434
435
fun createDynamicServices() {
436
// Configuration-driven parameters
437
val config = loadConfiguration()
438
439
val apiService = get<ApiService> {
440
parametersOf(config.apiUrl, config.apiKey)
441
}
442
443
// Runtime-computed parameters
444
val validator = get<UserValidator> {
445
parametersOf(
446
computeValidationRules(),
447
isStrictModeEnabled()
448
)
449
}
450
451
// Nested parameter creation
452
val sessionManager = get<SessionManager> {
453
parametersOf(
454
getCurrentUserId(),
455
getUserPermissions(),
456
SessionConfig.builder()
457
.timeout(config.sessionTimeout)
458
.secure(config.isSecure)
459
.build()
460
)
461
}
462
}
463
}
464
```
465
466
### Parameter Validation & Error Handling
467
468
Handle parameter-related errors and validation.
469
470
```kotlin { .api }
471
// Parameter-related exceptions
472
class NoParameterFoundException(message: String) : RuntimeException(message)
473
class DefinitionParameterException(message: String) : RuntimeException(message)
474
```
475
476
**Usage Examples:**
477
478
```kotlin
479
import org.koin.dsl.module
480
import org.koin.core.parameter.parametersOf
481
482
val validatedModule = module {
483
factory<EmailService> { params ->
484
try {
485
val smtpHost = params.get<String>(0)
486
val port = params.get<Int>(1)
487
val username = params.getOrNull<String>(2)
488
val password = params.getOrNull<String>(3)
489
490
// Validate parameters
491
require(smtpHost.isNotBlank()) { "SMTP host cannot be blank" }
492
require(port in 1..65535) { "Port must be between 1 and 65535" }
493
494
EmailServiceImpl(smtpHost, port, username, password)
495
} catch (e: Exception) {
496
throw DefinitionParameterException("Failed to create EmailService: ${e.message}")
497
}
498
}
499
}
500
501
class EmailController : KoinComponent {
502
503
fun sendEmail() {
504
try {
505
val emailService = get<EmailService> {
506
parametersOf("smtp.example.com", 587, "user@example.com", "password")
507
}
508
emailService.send("Hello World!")
509
} catch (e: NoParameterFoundException) {
510
logger.error("Missing required parameters for EmailService")
511
} catch (e: DefinitionParameterException) {
512
logger.error("Invalid parameters for EmailService: ${e.message}")
513
}
514
}
515
}
516
```
517
518
## Best Practices
519
520
### Qualifier Naming Conventions
521
522
```kotlin
523
// Use descriptive names
524
single<Database>(named("userDatabase")) { UserDatabase() }
525
single<Database>(named("analyticsDatabase")) { AnalyticsDatabase() }
526
527
// Use enums for related qualifiers
528
enum class CacheType { MEMORY, REDIS, DISK }
529
single<Cache>(named(CacheType.MEMORY)) { MemoryCache() }
530
single<Cache>(named(CacheType.REDIS)) { RedisCache() }
531
532
// Use type qualifiers for marker interfaces
533
interface Primary
534
interface Secondary
535
single<Service>(named<Primary>()) { PrimaryService() }
536
single<Service>(named<Secondary>()) { SecondaryService() }
537
```
538
539
### Parameter Patterns
540
541
```kotlin
542
// Use parameter objects for complex configurations
543
data class DatabaseConfig(
544
val host: String,
545
val port: Int,
546
val database: String,
547
val credentials: Credentials
548
)
549
550
factory<DatabaseConnection> { params ->
551
val config = params.get<DatabaseConfig>(0)
552
DatabaseConnectionImpl(config)
553
}
554
555
// Use builders for optional parameters
556
factory<HttpClient> { params ->
557
val builder = HttpClient.Builder()
558
.baseUrl(params.get<String>(0))
559
.timeout(params.getOrNull<Int>(1) ?: 30)
560
561
params.getOrNull<Map<String, String>>(2)?.let { headers ->
562
builder.headers(headers)
563
}
564
565
builder.build()
566
}
567
```
568
569
## Types
570
571
```kotlin { .api }
572
typealias ParametersDefinition = () -> ParametersHolder
573
typealias QualifierValue = String
574
575
// Parameter access interface
576
interface ParameterAccess {
577
fun <T> get(index: Int): T
578
fun <T> getOrNull(index: Int): T?
579
fun size(): Int
580
fun isEmpty(): Boolean
581
}
582
```