Core dependency injection framework for Kotlin multiplatform applications with DSL-based configuration and type-safe dependency resolution.
—
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.
Base interface for creating type-safe qualifiers to distinguish between instances.
/**
* Base qualifier interface for distinguishing instances
*/
interface Qualifier {
/**
* String value of the qualifier
*/
val value: String
}Create qualifiers using string values for simple naming scenarios.
/**
* Create string-based qualifier
* @param name - String identifier for the qualifier
* @return Qualifier instance
*/
fun named(name: String): Qualifier
/**
* Create enum-based qualifier
* @param name - Enum value for the qualifier
* @return Qualifier instance
*/
fun named(name: Enum<*>): Qualifier
/**
* Alternative string qualifier function
* @param name - String identifier for the qualifier
* @return Qualifier instance
*/
fun qualifier(name: String): Qualifier
/**
* Alternative enum qualifier function
* @param name - Enum value for the qualifier
* @return Qualifier instance
*/
fun qualifier(name: Enum<*>): Qualifier
/**
* Short form string qualifier
* @param name - String identifier for the qualifier
* @return Qualifier instance
*/
fun _q(name: String): QualifierUsage Examples:
import org.koin.core.qualifier.named
import org.koin.core.qualifier.qualifier
import org.koin.core.qualifier._q
import org.koin.dsl.module
enum class DatabaseType { PRIMARY, CACHE, ANALYTICS }
val qualifierModule = module {
// String qualifiers
single<Database>(named("primary")) { PostgreSQLDatabase() }
single<Database>(named("cache")) { RedisDatabase() }
single<Database>(qualifier("analytics")) { ClickHouseDatabase() }
// Enum qualifiers
single<ApiClient>(named(DatabaseType.PRIMARY)) { PrimaryApiClient() }
single<ApiClient>(named(DatabaseType.CACHE)) { CacheApiClient() }
// Short form qualifiers
single<Logger>(_q("file")) { FileLogger() }
single<Logger>(_q("console")) { ConsoleLogger() }
// Using qualifiers in dependencies
single<UserService> {
UserServiceImpl(
database = get(named("primary")),
cache = get(named("cache")),
logger = get(_q("file"))
)
}
}
// Usage in components
class DataService : KoinComponent {
private val primaryDb: Database by inject(named("primary"))
private val cacheDb: Database by inject(named("cache"))
private val analyticsDb: Database by inject(qualifier("analytics"))
fun processData() {
val data = primaryDb.query("SELECT * FROM users")
cacheDb.store("users", data)
analyticsDb.track("users_queried", data.size)
}
}Create qualifiers using type information for strongly-typed scenarios.
/**
* Create type-based qualifier using reified generics
* @return Type qualifier based on T
*/
inline fun <reified T> named(): Qualifier
/**
* Create type-based qualifier using reified generics
* @return Type qualifier based on T
*/
inline fun <reified T> qualifier(): Qualifier
/**
* Short form type-based qualifier
* @return Type qualifier based on T
*/
inline fun <reified T> _q(): Qualifier
/**
* Type-based qualifier implementation
* @param type - KClass representing the type
*/
class TypeQualifier(type: KClass<*>) : QualifierUsage Examples:
import org.koin.core.qualifier.named
import org.koin.core.qualifier.qualifier
import org.koin.core.qualifier._q
import org.koin.dsl.module
// Marker classes for type qualifiers
class PrimaryDatabase
class CacheDatabase
class AnalyticsDatabase
val typeQualifierModule = module {
// Type-based qualifiers
single<Database>(named<PrimaryDatabase>()) { PostgreSQLDatabase() }
single<Database>(qualifier<CacheDatabase>()) { RedisDatabase() }
single<Database>(_q<AnalyticsDatabase>()) { ClickHouseDatabase() }
// Scope qualifiers using types
scope(named<UserScope>()) {
scoped<UserService> { UserServiceImpl(get(named<PrimaryDatabase>())) }
scoped<UserCache> { UserCacheImpl(get(qualifier<CacheDatabase>())) }
}
}
// Usage with type safety
class AnalyticsService : KoinComponent {
private val analyticsDb: Database by inject(_q<AnalyticsDatabase>())
private val primaryDb: Database by inject(named<PrimaryDatabase>())
fun generateReport() {
val data = primaryDb.query("SELECT * FROM analytics")
val report = analyticsDb.process(data)
// Process report...
}
}Built-in qualifier implementations for different use cases.
/**
* String-based qualifier implementation
* @param value - String identifier
*/
data class StringQualifier(override val value: String) : Qualifier
/**
* Type-based qualifier implementation
* @param type - KClass representing the type
*/
class TypeQualifier(type: KClass<*>) : Qualifier {
override val value: String
}
typealias QualifierValue = StringUsage Examples:
import org.koin.core.qualifier.StringQualifier
import org.koin.core.qualifier.TypeQualifier
class CustomQualifierService : KoinComponent {
fun demonstrateQualifiers() {
// Create qualifiers programmatically
val stringQual = StringQualifier("custom")
val typeQual = TypeQualifier(String::class)
// Use in dependency resolution
val customService = get<MyService>(stringQual)
val typedService = get<MyService>(typeQual)
// Qualifier values are accessible
println("String qualifier: ${stringQual.value}")
println("Type qualifier: ${typeQual.value}")
}
}Runtime parameter injection for dynamic dependency configuration.
/**
* Parameter container for dependency injection
* @param values - Mutable list of parameter values
* @param useIndexedValues - Whether to use indexed parameter access
*/
class ParametersHolder(
private val values: MutableList<Any?> = mutableListOf(),
private val useIndexedValues: Boolean? = null
) {
/**
* Get parameter by index
* @param index - Parameter index
* @return Parameter value cast to T
*/
fun <T> get(index: Int): T
/**
* Get parameter by index with null safety
* @param index - Parameter index
* @return Parameter value cast to T or null
*/
fun <T> getOrNull(index: Int): T?
/**
* Set parameter at index
* @param index - Parameter index
* @param value - Parameter value
*/
fun <T> set(index: Int, value: T)
/**
* Get parameter at index (alias for get)
* @param index - Parameter index
* @return Parameter value cast to T
*/
fun <T> elementAt(index: Int): T
/**
* Get number of parameters
* @return Parameter count
*/
fun size(): Int
/**
* Check if parameters are empty
* @return True if no parameters
*/
fun isEmpty(): Boolean
/**
* Add parameter to end
* @param value - Parameter value
*/
fun add(value: Any?)
/**
* Insert parameter at index
* @param index - Target index
* @param value - Parameter value
*/
fun insert(index: Int, value: Any?)
// Component functions for destructuring
operator fun component1(): Any?
operator fun component2(): Any?
operator fun component3(): Any?
operator fun component4(): Any?
operator fun component5(): Any?
}Create parameter holders using different patterns.
/**
* Create parameters from variable arguments
* @param values - Variable number of parameter values
* @return ParametersHolder with values
*/
fun parametersOf(vararg values: Any?): ParametersHolder
/**
* Create indexed parameters from array
* @param values - Array of parameter values
* @return ParametersHolder with indexed access
*/
fun parameterArrayOf(vararg values: Any?): ParametersHolder
/**
* Create parameters from set/collection
* @param values - Set of parameter values
* @return ParametersHolder with set-based values
*/
fun parameterSetOf(vararg values: Any?): ParametersHolder
/**
* Create empty parameter holder
* @return Empty ParametersHolder
*/
fun emptyParametersHolder(): ParametersHolderUsage Examples:
import org.koin.core.parameter.parametersOf
import org.koin.core.parameter.parameterArrayOf
import org.koin.core.parameter.emptyParametersHolder
import org.koin.dsl.module
// Module with parameterized dependencies
val parameterModule = module {
factory<HttpClient> { params ->
val baseUrl = params.get<String>(0)
val timeout = params.get<Int>(1)
val retries = params.getOrNull<Int>(2) ?: 3
HttpClientImpl(baseUrl, timeout, retries)
}
factory<DatabaseConnection> { params ->
val (host, port, database, user, password) = params
DatabaseConnectionImpl(host as String, port as Int, database as String, user as String, password as String)
}
}
// Usage with parameters
class NetworkService : KoinComponent {
fun createClients() {
// Simple parameters
val apiClient = get<HttpClient> {
parametersOf("https://api.example.com", 30)
}
// Parameters with optional values
val clientWithRetries = get<HttpClient> {
parametersOf("https://api.example.com", 60, 5)
}
// Array parameters
val configuredClient = get<HttpClient> {
parameterArrayOf("https://secure-api.example.com", 45)
}
// Destructured parameters
val dbConnection = get<DatabaseConnection> {
parametersOf("localhost", 5432, "myapp", "user", "password")
}
// Empty parameters
val defaultService = get<DefaultService> { emptyParametersHolder() }
}
}Use parameters within dependency definitions for dynamic configuration.
typealias ParametersDefinition = () -> ParametersHolderUsage Examples:
import org.koin.dsl.module
import org.koin.core.parameter.parametersOf
val dynamicModule = module {
// Single with parameters
single<ApiService> { params ->
val baseUrl = params.get<String>(0)
val apiKey = params.getOrNull<String>(1) ?: "default-key"
ApiServiceImpl(baseUrl, apiKey)
}
// Factory with parameter validation
factory<UserValidator> { params ->
val rules = params.get<ValidationRules>(0)
val strict = params.getOrNull<Boolean>(1) ?: false
require(rules.isValid()) { "Invalid validation rules" }
UserValidatorImpl(rules, strict)
}
// Scoped with complex parameters
scope(named<SessionScope>()) {
scoped<SessionManager> { params ->
val userId = params.get<String>(0)
val permissions = params.get<Set<Permission>>(1)
val config = params.getOrNull<SessionConfig>(2) ?: SessionConfig.default()
SessionManagerImpl(userId, permissions, config)
}
}
}
// Advanced parameter usage
class ConfigurableService : KoinComponent {
fun createDynamicServices() {
// Configuration-driven parameters
val config = loadConfiguration()
val apiService = get<ApiService> {
parametersOf(config.apiUrl, config.apiKey)
}
// Runtime-computed parameters
val validator = get<UserValidator> {
parametersOf(
computeValidationRules(),
isStrictModeEnabled()
)
}
// Nested parameter creation
val sessionManager = get<SessionManager> {
parametersOf(
getCurrentUserId(),
getUserPermissions(),
SessionConfig.builder()
.timeout(config.sessionTimeout)
.secure(config.isSecure)
.build()
)
}
}
}Handle parameter-related errors and validation.
// Parameter-related exceptions
class NoParameterFoundException(message: String) : RuntimeException(message)
class DefinitionParameterException(message: String) : RuntimeException(message)Usage Examples:
import org.koin.dsl.module
import org.koin.core.parameter.parametersOf
val validatedModule = module {
factory<EmailService> { params ->
try {
val smtpHost = params.get<String>(0)
val port = params.get<Int>(1)
val username = params.getOrNull<String>(2)
val password = params.getOrNull<String>(3)
// Validate parameters
require(smtpHost.isNotBlank()) { "SMTP host cannot be blank" }
require(port in 1..65535) { "Port must be between 1 and 65535" }
EmailServiceImpl(smtpHost, port, username, password)
} catch (e: Exception) {
throw DefinitionParameterException("Failed to create EmailService: ${e.message}")
}
}
}
class EmailController : KoinComponent {
fun sendEmail() {
try {
val emailService = get<EmailService> {
parametersOf("smtp.example.com", 587, "user@example.com", "password")
}
emailService.send("Hello World!")
} catch (e: NoParameterFoundException) {
logger.error("Missing required parameters for EmailService")
} catch (e: DefinitionParameterException) {
logger.error("Invalid parameters for EmailService: ${e.message}")
}
}
}// Use descriptive names
single<Database>(named("userDatabase")) { UserDatabase() }
single<Database>(named("analyticsDatabase")) { AnalyticsDatabase() }
// Use enums for related qualifiers
enum class CacheType { MEMORY, REDIS, DISK }
single<Cache>(named(CacheType.MEMORY)) { MemoryCache() }
single<Cache>(named(CacheType.REDIS)) { RedisCache() }
// Use type qualifiers for marker interfaces
interface Primary
interface Secondary
single<Service>(named<Primary>()) { PrimaryService() }
single<Service>(named<Secondary>()) { SecondaryService() }// Use parameter objects for complex configurations
data class DatabaseConfig(
val host: String,
val port: Int,
val database: String,
val credentials: Credentials
)
factory<DatabaseConnection> { params ->
val config = params.get<DatabaseConfig>(0)
DatabaseConnectionImpl(config)
}
// Use builders for optional parameters
factory<HttpClient> { params ->
val builder = HttpClient.Builder()
.baseUrl(params.get<String>(0))
.timeout(params.getOrNull<Int>(1) ?: 30)
params.getOrNull<Map<String, String>>(2)?.let { headers ->
builder.headers(headers)
}
builder.build()
}typealias ParametersDefinition = () -> ParametersHolder
typealias QualifierValue = String
// Parameter access interface
interface ParameterAccess {
fun <T> get(index: Int): T
fun <T> getOrNull(index: Int): T?
fun size(): Int
fun isEmpty(): Boolean
}Install with Tessl CLI
npx tessl i tessl/maven-io-insert-koin--koin-core-jvm