dependencies-kt

Modules

We often want to split dependencies into reusable modules with parts that can be swapped out for tests.

val MyModule = module("my-module") {
  // access to `MutableDI` here
  single<Int> { Random.nextInt() } 
}

val scope = DIScope()

val di: DI = scope.load(MyModule)
val again = scope.load(MyModule)

// Module only gets loaded once per scope, so the two Random ints will be equal here!
di.get<Int>() == again.get<Int>()

Modules are closeable

Modules can addCloseable and be closed either via scope.unload or by calling close on them:

val MyModule = module("my-module") {
    addCloseable {
        println("Closed!")
    }
}
val scope = DIScope()
scope.load(MyModule)
scope.unload(MyModule) // prints "Closed!"

// alternatively
val di = scope.load(MyModule)
di.close() // prints "Closed!"

Overriding modules

Modules can have values changed using override. This essentially calls the insides before the modle's code runs, while still referencing the correct module key:

val MyModule = module("my-module") {
    val string by single { "My long string message here" }
    val length by single<Int>("length") { string.length }

    println("Got $string with length $length")
}

// An override switches out the string provider
val WithOverride = MyModule.override {
    single(ignoreOverride = true) { "Changed" }
}

val scope = DIScope()
scope.load(WithOverride) // prints "Got Changed with length 7" 
scope.load(MyModule) // Returns same DI instance as above, the keys for `withOveride` and `myModule` are equivalent