CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-kodein-di--kodein-di

KOtlin DEpendency INjection - A straightforward and yet very useful dependency retrieval container for Kotlin Multiplatform

Pending
Overview
Eval results
Files

container-configuration.mddocs/

Container Configuration

Core DI container creation and configuration functionality for managing dependency injection containers, modules, and lifecycle callbacks.

Capabilities

DI Container Creation

Creates and configures the main dependency injection container with customizable settings and initialization blocks.

/**
 * Main dependency injection container interface
 */
interface DI : DIAware {
    val container: DIContainer
    
    companion object {
        /**
         * Creates a DI instance with configuration block
         * @param allowSilentOverride Whether to allow implicit binding overrides
         * @param init Configuration block for defining bindings
         * @return Configured DI container
         */
        operator fun invoke(
            allowSilentOverride: Boolean = false,
            init: MainBuilder.() -> Unit
        ): DI
        
        /**
         * Creates a lazily initialized DI instance
         * @param allowSilentOverride Whether to allow implicit binding overrides
         * @param init Configuration block for defining bindings
         * @return LazyDI wrapper that initializes on first access
         */
        fun lazy(
            allowSilentOverride: Boolean = false,
            init: MainBuilder.() -> Unit
        ): LazyDI
        
        /**
         * Creates a direct DI instance for immediate access
         * @param allowSilentOverride Whether to allow implicit binding overrides
         * @param init Configuration block for defining bindings
         * @return DirectDI instance for immediate dependency access
         */
        fun direct(
            allowSilentOverride: Boolean = false,
            init: MainBuilder.() -> Unit
        ): DirectDI
        
        /**
         * Creates DI with delayed callback execution (internal API)
         * @param allowSilentOverride Whether to allow implicit binding overrides
         * @param init Configuration block for defining bindings
         * @return Pair of DI instance and callback function
         */
        fun withDelayedCallbacks(
            allowSilentOverride: Boolean = false,
            init: MainBuilder.() -> Unit
        ): Pair<DI, () -> Unit>
        
        /**
         * Creates DI from a list of modules
         * @param modules List of modules to import
         * @return DI instance with all module bindings
         */
        fun from(modules: List<Module>): DI
        
        /** Global default for full error descriptions */
        var defaultFullDescriptionOnError: Boolean
        
        /** Global default for full container tree in errors */
        var defaultFullContainerTreeOnError: Boolean
    }
}

Lazy DI Initialization

Deferred DI initialization patterns for cases where the container cannot be immediately created.

/**
 * Lazily initialized DI container
 * @param f Function that creates the DI instance when needed
 */
class LazyDI(f: () -> DI) : DI {
    // Delegates all DI operations to the lazily created instance
}

/**
 * Manually initialized DI container for late binding scenarios
 */
class LateInitDI : DI {
    /**
     * The base DI instance (must be set before use)
     */
    lateinit var baseDI: DI
}

Module System

Reusable configuration modules for organizing and sharing binding definitions across DI containers.

/**
 * Reusable configuration module for dependency bindings
 * @param allowSilentOverride Whether this module allows implicit overrides
 * @param prefix String prefix for all bindings in this module
 * @param init Configuration block defining the module's bindings
 */
data class DI.Module(
    val allowSilentOverride: Boolean = false,
    val prefix: String = "",
    val init: Builder.() -> Unit
) {
    val name: String // Module name (required)
    
    /**
     * Named module constructor
     * @param name Unique name for this module
     * @param allowSilentOverride Whether this module allows implicit overrides
     * @param prefix String prefix for all bindings in this module
     * @param init Configuration block defining the module's bindings
     */
    constructor(
        name: String,
        allowSilentOverride: Boolean = false,
        prefix: String = "",
        init: Builder.() -> Unit
    )
    
    /**
     * Property delegate support for automatic naming
     */
    operator fun getValue(thisRef: Any?, property: KProperty<*>): Module
}

Builder Interfaces

DSL interfaces for configuring DI containers with bindings, modules, and lifecycle callbacks.

/**
 * Main builder interface for DI configuration
 */
interface DI.Builder : BindBuilder<Any>, BindBuilder.WithScope<Any> {
    val containerBuilder: DIContainer.Builder
    
    /**
     * Import a module into this DI configuration
     * @param module The module to import
     * @param allowOverride Whether to allow binding overrides
     */
    fun import(module: Module, allowOverride: Boolean = false)
    
    /**
     * Import multiple modules into this DI configuration
     * @param modules Modules to import
     * @param allowOverride Whether to allow binding overrides
     */
    fun importAll(vararg modules: Module, allowOverride: Boolean = false)
    fun importAll(modules: Iterable<Module>, allowOverride: Boolean = false)
    
    /**
     * Import a module only once (checked by name)
     * @param module The module to import once
     * @param allowOverride Whether to allow binding overrides
     */
    fun importOnce(module: Module, allowOverride: Boolean = false)
    
    /**
     * Register a callback to be called when DI is ready
     * @param cb Callback function receiving DirectDI instance
     */
    fun onReady(cb: DirectDI.() -> Unit)
    
    /**
     * Register a context translator for scope management
     * @param translator Context translator instance
     */
    fun RegisterContextTranslator(translator: ContextTranslator<*, *>)
}

/**
 * Extended builder for main DI creation with additional configuration
 */
interface DI.MainBuilder : Builder {
    /** Whether to include qualified names in error messages */
    var fullDescriptionOnError: Boolean
    
    /** Whether to include full container tree in NotFoundException */
    var fullContainerTreeOnError: Boolean
    
    /** List of external sources for fallback binding resolution */
    val externalSources: MutableList<ExternalSource>
    
    /**
     * Extend this DI with another DI container
     * @param di The DI container to extend from
     * @param allowOverride Whether to allow binding overrides
     * @param copy Copy specification for which bindings to copy
     */
    fun extend(di: DI, allowOverride: Boolean = false, copy: Copy = Copy.NonCached)
    fun extend(directDI: DirectDI, allowOverride: Boolean = false, copy: Copy = Copy.NonCached)
}

Container Extension and Copy Strategies

Advanced container composition and extension patterns for building complex DI hierarchies.

/**
 * Copy specification for container extension
 */
sealed class Copy {
    /** Copy no bindings (default) */
    object None : Copy()
    
    /** Copy all bindings */
    object All : Copy()
    
    /** Copy only non-cached bindings (providers, factories) */
    object NonCached : Copy()
}

Usage Examples:

// Basic DI container creation
val di = DI {
    bind<DataService>() with singleton { DataServiceImpl() }
    bind<UserRepository>() with provider { UserRepositoryImpl(instance()) }
}

// Module definition and usage
val dataModule = DI.Module("data") {
    bind<Database>() with singleton { SQLiteDatabase() }
    bind<UserDao>() with provider { UserDaoImpl(instance()) }
}

val serviceModule = DI.Module("services") {
    bind<UserService>() with provider { UserServiceImpl(instance()) }
}

val appDI = DI {
    import(dataModule)
    import(serviceModule)
    
    // Override specific bindings
    bind<Database>(overrides = true) with singleton { 
        if (BuildConfig.DEBUG) MockDatabase() else SQLiteDatabase()
    }
}

// Lazy DI initialization
val lazyDI = DI.lazy {
    bind<ConfigService>() with singleton { ConfigServiceImpl() }
    onReady { 
        // Initialization code when DI is ready
        println("DI container initialized")
    }
}

// Container extension
val extendedDI = DI {
    extend(appDI, allowOverride = true, copy = Copy.NonCached)
    
    // Add additional bindings
    bind<TestService>() with singleton { TestServiceImpl() }
}

// Late initialization pattern
class Application : DIAware {
    private val lateInitDI = LateInitDI()
    override val di: DI = lateInitDI
    
    fun initialize() {
        lateInitDI.baseDI = DI {
            bind<AppService>() with singleton { AppServiceImpl() }
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-kodein-di--kodein-di

docs

advanced-features.md

binding-dsl.md

container-configuration.md

direct-access.md

index.md

lazy-property-delegation.md

scoping-and-context.md

tile.json