or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdbinding-dsl.mdcontainer-configuration.mddirect-access.mdindex.mdlazy-property-delegation.mdscoping-and-context.md

index.mddocs/

0

# 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

```