KOtlin DEpendency INjection - A straightforward and yet very useful dependency retrieval container for Kotlin Multiplatform
npx @tessl/cli install tessl/maven-org-kodein-di--kodein-di@7.26.00
# Kodein-DI
1
2
Kodein-DI is a comprehensive dependency injection framework for Kotlin Multiplatform applications that provides effortless dependency retrieval and container management. It enables lazy instantiation of dependencies, eliminates concerns about initialization order, and supports binding classes or interfaces to their instances or providers with a declarative DSL.
3
4
## Package Information
5
6
- **Package Name**: kodein-di
7
- **Package Type**: maven
8
- **Language**: Kotlin Multiplatform
9
- **Installation**: `implementation("org.kodein.di:kodein-di:7.26.1")`
10
11
## Core Imports
12
13
```kotlin
14
import org.kodein.di.*
15
```
16
17
For specific functionality:
18
19
```kotlin
20
import org.kodein.di.DI
21
import org.kodein.di.DIAware
22
import org.kodein.di.DirectDI
23
import org.kodein.di.bindSingleton
24
import org.kodein.di.bindProvider
25
import org.kodein.di.bindFactory
26
import org.kodein.di.instance
27
import org.kodein.di.provider
28
import org.kodein.di.factory
29
```
30
31
## Basic Usage
32
33
```kotlin
34
import org.kodein.di.*
35
36
// Define interfaces and classes
37
interface DataSource
38
class SqliteDataSource : DataSource
39
interface UserService
40
class UserServiceImpl(private val dataSource: DataSource) : UserService
41
42
// Create DI container
43
val di = DI {
44
bind<DataSource>() with singleton { SqliteDataSource() }
45
bind<UserService>() with provider { UserServiceImpl(instance()) }
46
constant("appName") with "MyApp"
47
}
48
49
// Use dependency injection
50
class MyController : DIAware {
51
override val di: DI = di
52
53
private val userService: UserService by instance()
54
private val appName: String by constant()
55
56
fun handleRequest() {
57
// Use injected dependencies
58
println("Handling request in $appName")
59
}
60
}
61
62
// Direct access (immediate retrieval)
63
val directDI = di.direct
64
val userService = directDI.instance<UserService>()
65
```
66
67
## Architecture
68
69
Kodein-DI is built around several key components:
70
71
- **DI Container**: Main dependency injection container that stores bindings and manages instances
72
- **Binding DSL**: Declarative syntax for configuring dependencies (singleton, provider, factory, instance, multiton)
73
- **Retrieval Patterns**: Both lazy property delegation (DIAware) and direct access (DirectDI) for dependency retrieval
74
- **Scoping System**: Context-aware dependency management with hierarchical scopes and custom scope definitions
75
- **Module System**: Reusable configuration modules for organizing and sharing binding definitions
76
- **Type Safety**: Full Kotlin type safety with generic preservation and TypeToken integration
77
78
## Capabilities
79
80
### Container Configuration
81
82
Core DI container creation and configuration with binding DSL for defining how dependencies are created and managed.
83
84
```kotlin { .api }
85
interface DI : DIAware {
86
val container: DIContainer
87
88
companion object {
89
operator fun invoke(
90
allowSilentOverride: Boolean = false,
91
init: MainBuilder.() -> Unit
92
): DI
93
94
fun lazy(
95
allowSilentOverride: Boolean = false,
96
init: MainBuilder.() -> Unit
97
): LazyDI
98
99
fun direct(
100
allowSilentOverride: Boolean = false,
101
init: MainBuilder.() -> Unit
102
): DirectDI
103
104
fun withDelayedCallbacks(
105
allowSilentOverride: Boolean = false,
106
init: MainBuilder.() -> Unit,
107
): Pair<DI, () -> Unit>
108
109
fun from(modules: List<Module>): DI
110
111
var defaultFullDescriptionOnError: Boolean
112
var defaultFullContainerTreeOnError: Boolean
113
}
114
}
115
116
data class Module(
117
val allowSilentOverride: Boolean = false,
118
val prefix: String = "",
119
val init: Builder.() -> Unit
120
) {
121
val name: String
122
constructor(
123
name: String,
124
allowSilentOverride: Boolean = false,
125
prefix: String = "",
126
init: Builder.() -> Unit,
127
)
128
operator fun getValue(thisRef: Any?, property: KProperty<*>): Module
129
}
130
```
131
132
[Container Configuration](./container-configuration.md)
133
134
### Binding DSL
135
136
Declarative syntax for binding types to their implementations with various creation patterns including singleton, provider, factory, instance, and multiton.
137
138
```kotlin { .api }
139
interface DI.Builder {
140
fun <T : Any> Bind(type: TypeToken<out T>, tag: Any? = null, overrides: Boolean? = null): TypeBinder<T>
141
fun <T : Any> Bind(tag: Any? = null, overrides: Boolean? = null, binding: DIBinding<*, *, T>)
142
fun constant(tag: Any, overrides: Boolean? = null): ConstantBinder
143
fun <T : Any> Delegate(type: TypeToken<out T>, tag: Any? = null, overrides: Boolean? = null): DelegateBinder<T>
144
fun import(module: Module, allowOverride: Boolean = false)
145
fun importAll(vararg modules: Module, allowOverride: Boolean = false)
146
fun importOnce(module: Module, allowOverride: Boolean = false)
147
fun onReady(cb: DirectDI.() -> Unit)
148
149
// Set binding methods
150
fun <T : Any> BindInSet(tag: Any? = null, overrides: Boolean? = null, type: TypeToken<out T>, creator: SetBinder<T>.() -> Unit)
151
fun <T : Any> InBindSet(tag: Any? = null, overrides: Boolean? = null, type: TypeToken<out T>, creator: SetBinder<T>.() -> Unit)
152
fun <T : Any> AddBindInSet(tag: Any? = null, overrides: Boolean? = null, binding: DIBinding<*, *, T>)
153
}
154
155
fun <T : Any> DI.BindBuilder<*>.singleton(
156
creator: NoArgBindingDI<*>.() -> T
157
): Singleton<*, T>
158
159
fun <T : Any> DI.BindBuilder<*>.provider(
160
creator: NoArgBindingDI<*>.() -> T
161
): Provider<*, T>
162
163
fun <A, T : Any> DI.BindBuilder<*>.factory(
164
creator: BindingDI<*>.(A) -> T
165
): Factory<*, A, T>
166
```
167
168
[Binding DSL](./binding-dsl.md)
169
170
### Lazy Property Delegation
171
172
Property delegation pattern for lazy dependency retrieval using DIAware interface with automatic initialization and caching.
173
174
```kotlin { .api }
175
interface DIAware {
176
val di: DI
177
val diContext: DIContext<*>
178
val diTrigger: DITrigger?
179
}
180
181
fun <T : Any> DIAware.instance(tag: Any? = null): LazyDelegate<T>
182
fun <T : Any> DIAware.provider(tag: Any? = null): LazyDelegate<() -> T>
183
fun <A, T : Any> DIAware.factory(tag: Any? = null): LazyDelegate<(A) -> T>
184
fun <T : Any> DIAware.constant(): LazyDelegate<T>
185
```
186
187
[Lazy Property Delegation](./lazy-property-delegation.md)
188
189
### Direct Access
190
191
Immediate dependency retrieval without property delegation for cases requiring direct access to dependencies.
192
193
```kotlin { .api }
194
interface DirectDI : DirectDIBase {
195
fun <T : Any> Instance(type: TypeToken<T>, tag: Any? = null): T
196
fun <T : Any> Provider(type: TypeToken<T>, tag: Any? = null): () -> T
197
fun <A, T : Any> Factory(argType: TypeToken<in A>, type: TypeToken<T>, tag: Any? = null): (A) -> T
198
fun On(context: DIContext<*>): DirectDI
199
}
200
201
interface DirectDIAware {
202
val directDI: DirectDI
203
}
204
```
205
206
[Direct Access](./direct-access.md)
207
208
### Scoping and Context
209
210
Context-aware dependency management with support for hierarchical scopes, context translation, and lifecycle management.
211
212
```kotlin { .api }
213
interface DIContext<C : Any> {
214
val type: TypeToken<in C>
215
val value: C
216
217
data class Value<C : Any>(override val type: TypeToken<in C>, override val value: C) : DIContext<C>
218
class Lazy<C : Any>(override val type: TypeToken<in C>, val getValue: () -> C) : DIContext<C>
219
}
220
221
interface Scope<C> {
222
fun getRegistry(context: C): ScopeRegistry
223
}
224
225
interface ContextTranslator<C, S> {
226
fun translate(key: DI.Key<*, *, *>, context: C): S?
227
}
228
```
229
230
[Scoping and Context](./scoping-and-context.md)
231
232
### Advanced Features
233
234
Advanced dependency injection patterns including constructor injection, external sources, binding search, and sub-DI creation.
235
236
```kotlin { .api }
237
fun <T> DirectDIAware.new(constructor: () -> T): T
238
fun <P1, T> DirectDIAware.new(constructor: (P1) -> T): T
239
240
interface ExternalSource {
241
fun <C : Any, A, T : Any> getFactory(
242
key: DI.Key<C, A, T>,
243
context: C
244
): ((A) -> T)?
245
}
246
247
fun DirectDIAware.subDI(
248
allowSilentOverride: Boolean = false,
249
copy: Copy = Copy.NonCached,
250
init: DI.MainBuilder.() -> Unit
251
): DI
252
```
253
254
[Advanced Features](./advanced-features.md)
255
256
## Exception Handling
257
258
Kodein-DI defines several specific exception types for different error conditions:
259
260
```kotlin { .api }
261
class DI.NotFoundException(val key: Key<*, *, *>, message: String) : RuntimeException(message)
262
class DI.DependencyLoopException(message: String) : RuntimeException(message)
263
class DI.OverridingException(message: String) : RuntimeException(message)
264
class DI.NoResultException(val search: SearchSpecs, message: String) : RuntimeException(message)
265
class DI.UnusedParameterException(message: String, cause: Exception? = null) : RuntimeException(message, cause)
266
```
267
268
## Type System
269
270
```kotlin { .api }
271
data class DI.Key<in C : Any, in A, out T : Any>(
272
val contextType: TypeToken<in C>,
273
val argType: TypeToken<in A>,
274
val type: TypeToken<out T>,
275
val tag: Any?
276
)
277
278
interface Typed<A> {
279
val type: TypeToken<A>
280
val value: A
281
}
282
```