Modules
Group related services into reusable modules. Libraries ship a module, applications include it — with optional overrides.
What are modules?
A Kontainer module is a reusable block of service definitions. Instead of copying service registrations across projects, you define them once in a module and include it.
Modules are useful for:
- Library authors — bundle your library's services into a module users can drop in
- Large applications — organize services by feature area
- Customization — provide sensible defaults that users can override
Defining a simple module
import io.peekandpoke.ultra.kontainer.module
// Some services
interface Storage {
val name: String
}
class FileStorage : Storage {
override val name = "FileStorage"
}
class Database(val storage: Storage)
// Define the module
val databaseModule = module {
singleton(Database::class)
singleton(Storage::class, FileStorage::class)
} Using a module
val blueprint = kontainer {
module(databaseModule)
}
val kontainer = blueprint.create()
println(kontainer.get(Database::class).storage.name) // "FileStorage" Overriding module services
Any service defined by a module can be overridden. Just register the same type after including the module:
class MemoryStorage : Storage {
override val name = "MemoryStorage"
}
val blueprint = kontainer {
module(databaseModule)
// Override the Storage implementation
singleton(Storage::class, MemoryStorage::class)
}
val kontainer = blueprint.create()
println(kontainer.get(Database::class).storage.name) // "MemoryStorage" Parameterized modules
Modules can accept parameters — up to 5 — for configuration at inclusion time:
class Service(val sum: Int)
// Module with three parameters
val configModule = module { a: Int, b: Int, c: Int ->
instance(Service(a + b + c))
}
val blueprint = kontainer {
module(configModule, 1, 10, 100)
}
val kontainer = blueprint.create()
println(kontainer.get(Service::class).sum) // 111 Composing modules
Modules can include other modules, enabling layered architectures:
val coreModule = module {
singleton(Counter::class)
}
val appModule = module {
module(coreModule)
singleton(MyService::class)
}
val blueprint = kontainer {
module(appModule)
}