CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-insert-koin--koin-core-jvm

Core dependency injection framework for Kotlin multiplatform applications with DSL-based configuration and type-safe dependency resolution.

Pending
Overview
Eval results
Files

qualifiers-parameters.mddocs/

Qualifiers & Parameters

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.

Capabilities

Qualifier Interface

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
}

String-Based Qualifiers

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): Qualifier

Usage 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)
    }
}

Type-Based Qualifiers

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<*>) : Qualifier

Usage 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...
    }
}

Qualifier Implementations

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 = String

Usage 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}")
    }
}

Parameter System

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?
}

Parameter Factory Functions

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(): ParametersHolder

Usage 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() }
    }
}

Parameter Usage in Definitions

Use parameters within dependency definitions for dynamic configuration.

typealias ParametersDefinition = () -> ParametersHolder

Usage 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()
            )
        }
    }
}

Parameter Validation & Error Handling

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}")
        }
    }
}

Best Practices

Qualifier Naming Conventions

// 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() }

Parameter Patterns

// 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()
}

Types

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

docs

application-setup.md

component-integration.md

configuration-logging.md

constructor-reference.md

index.md

java-interop.md

module-definition.md

property-management.md

qualifiers-parameters.md

scope-management.md

tile.json