Global & Configurable Kodein DI
Introduction
The Configurable DI Plugin gives you :
- 
A ConfigurableDIclass that you can pass around and have different sections of your code configure its bindings.
- 
A DI.globalinstance that allows to have "one true" source.
The Configurable DI Plugin is an extension that is not proposed by default, this paradigm is in a separate module.
| Using or not using this is a matter of taste and is neither recommended nor discouraged. | 
Install
JVM
With Gradle
| If you are NOT using Gradle 6+, you should declare the use of the Gradle Metadata experimental feature settings.gradle.kts enableFeaturePreview("GRADLE_METADATA") | 
Add the MavenCentral repository:
buildscript {
    repositories {
        mavenCentral()
    }
}Then add the dependency:
dependencies {
    implementation 'org.kodein.di:kodein-di-conf:7.17.0'
}Add the dependency:
<dependencies>
    <dependency>
        <groupId>org.kodein.di</groupId>
        <artifactId>kodein-di-conf-jvm</artifactId>
        <version>7.17.0</version>
    </dependency>
</dependencies>| Use kodein-di-conf-jvm, as Kotlin/Multiplatform projects configuration does not work with Maven | 
JavaScript (Gradle)
Because Kodein-DI for JavaScript is compiled as a UMD module, it can be imported:
- 
In a browser: - 
as an AMD module (for example with RequireJS) (See index.html in the demo project). 
- 
Directly in an HTML page with a <script>tag (See index2.html in the demo project).
 
- 
- 
In NodeJS, as a regular CJS module. 
Add the MavenCentral repository:
buildscript {
    repositories {
        mavenCentral()
    }
}Then add the dependency:
dependencies {
    compile 'org.kodein.di:kodein-di-conf-js:7.17.0'
}Kotlin/Multiplatform (Gradle)
| Kodein-DI supports the following targets: androidArm32, androidArm64, iosArm32, iosArm64, iosX64, linuxArm32Hfp, linuxMips32, linuxMipsel32, linuxX64, macosX64, mingwX64 | 
Kodein-DI uses the new gradle native dependency model.
Add the MavenCentral repository:
buildscript {
    repositories {
        mavenCentral()
    }
}Then add the dependency:
kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation "org.kodein.di:kodein-di-conf:7.17.0"
            }
        }
    }
}ConfigurableDI
Configuring
You can import modules, extend DI objects, or add bindings inside this ConfigurableDI using addImport, addExtend and addConfig.
fun test() {
    val di = ConfigurableDI()
        .addModule(aModule)
        .addExtend(otherDI)
        .addConfig {
            bind<Dice> { provider { RandomDice(0, 5) } }
            bind<DataSource> { singleton { SqliteDS.open("path/to/file") } }
        }
}| The DIunderlying instance will effectively be constructed on first retrieval.
         Once it is constructed, trying to configure it will throw anIllegalStateException. | 
Retrieving
You can use a ConfigurableDI object like any DI object.
| Once you have retrieved the first value with a ConfigurableDI, trying to configure it will throw anIllegalStateException. | 
Mutating
A ConfigurableDI can be mutable.
val di = ConfigurableDI(mutable = true)| Using a mutable  | 
A mutable ConfigurableDI can be configured even after first retrieval.
fun test() {
    val di = ConfigurableDI(mutable = true)
    di.addModule(aModule)
    val ds: DataSource by di.instance()
    di.addModule(anotherModule) (1)
}| 1 | This would have failed if the ConfigurableDI was not mutable. | 
You can also use the clear method to remove all bindings.
The god complex: One True DI
Sometimes, you want one static DI for your entire application. E.g. you don’t want to have to hold & pass a DI instance throughout your application.
For these cases, the di-conf module proposes a static DI.global instance.
fun test() {
    DI.global.addModule(apiModule)
    DI.global.addModule(dbModule)
    val ds: DataSource by DI.global.instance()
}| Just like any  |