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

binding-dsl.mddocs/

0

# Binding DSL

1

2

Declarative syntax for binding types to their implementations with various creation patterns including singleton, provider, factory, instance, and multiton bindings.

3

4

## Capabilities

5

6

### Core Binding Methods

7

8

Generic binding methods that form the foundation of the DSL syntax for attaching types to their creation strategies.

9

10

```kotlin { .api }

11

/**

12

* Core binding interface for type-to-implementation mappings

13

*/

14

interface DI.Builder {

15

/**

16

* Start binding a specific type with optional tag and override settings

17

* @param type TypeToken representing the type to bind

18

* @param tag Optional tag for disambiguation

19

* @param overrides Whether this binding may override existing bindings

20

* @return TypeBinder for completing the binding with 'with' clause

21

*/

22

fun <T : Any> Bind(type: TypeToken<out T>, tag: Any? = null, overrides: Boolean? = null): TypeBinder<T>

23

24

/**

25

* Directly attach a pre-created binding to the container

26

* @param tag Optional tag for the binding

27

* @param overrides Whether this binding may override existing bindings

28

* @param binding The binding implementation to attach

29

*/

30

fun <T : Any> Bind(tag: Any? = null, overrides: Boolean? = null, binding: DIBinding<*, *, T>)

31

32

/**

33

* Create a constant binding with a specific tag

34

* @param tag Required tag for the constant

35

* @param overrides Whether this binding may override existing bindings

36

* @return ConstantBinder for completing the binding

37

*/

38

fun constant(tag: Any, overrides: Boolean? = null): ConstantBinder

39

40

/**

41

* Create a delegate binding that forwards to another binding

42

* @param type TypeToken for the type being delegated

43

* @param tag Optional tag for the delegation

44

* @param overrides Whether this binding may override existing bindings

45

* @return DelegateBinder for specifying the target binding

46

*/

47

fun <T : Any> Delegate(

48

type: TypeToken<out T>,

49

tag: Any? = null,

50

overrides: Boolean? = null

51

): DelegateBinder<T>

52

}

53

54

/**

55

* Type binder for completing binding syntax with 'with' keyword

56

*/

57

interface DI.Builder.TypeBinder<T : Any> {

58

/**

59

* Complete the binding by attaching a specific binding implementation

60

* @param binding The binding that creates instances of type T

61

*/

62

infix fun <C : Any, A> with(binding: DIBinding<in C, in A, out T>)

63

}

64

65

/**

66

* Constant binder for binding tagged constants

67

*/

68

interface DI.Builder.ConstantBinder {

69

/**

70

* Bind a constant value with specific type

71

* @param valueType TypeToken for the constant's type

72

* @param value The constant value to bind

73

*/

74

fun <T : Any> With(valueType: TypeToken<out T>, value: T)

75

}

76

77

/**

78

* Set binder for managing multiple bindings of the same type in a Set

79

*/

80

interface DI.Builder.SetBinder<T : Any> {

81

/**

82

* Add a binding to the set without adding it to the main container

83

* @param createBinding Function that creates the binding to add

84

*/

85

fun add(createBinding: () -> DIBinding<*, *, out T>)

86

87

/**

88

* Add a binding to both the set and the main container

89

* @param tag Optional tag for the individual binding

90

* @param overrides Whether this binding may override existing bindings

91

* @param createBinding Function that creates the binding to add

92

*/

93

fun bind(tag: Any? = null, overrides: Boolean? = null, createBinding: () -> DIBinding<*, *, out T>)

94

}

95

96

/**

97

* Argument set binder for managing multiple factory bindings of the same type in a Set

98

*/

99

interface DI.Builder.ArgSetBinder<A : Any, T : Any> {

100

/**

101

* Add a factory binding to the set without adding it to the main container

102

* @param createBinding Function that creates the factory binding to add

103

*/

104

fun add(createBinding: () -> DIBinding<*, in A, out T>)

105

106

/**

107

* Add a factory binding to both the set and the main container

108

* @param tag Optional tag for the individual binding

109

* @param overrides Whether this binding may override existing bindings

110

* @param createBinding Function that creates the factory binding to add

111

*/

112

fun bind(

113

tag: Any? = null,

114

overrides: Boolean? = null,

115

createBinding: () -> DIBinding<*, in A, out T>,

116

)

117

}

118

```

119

120

### Set Binding Methods

121

122

Methods for creating and managing set bindings that collect multiple implementations of the same interface.

123

124

```kotlin { .api }

125

/**

126

* Create a new set binding and configure it with multiple bindings

127

* @param tag Optional tag for the set binding

128

* @param overrides Whether this set binding may override existing bindings

129

* @param type TypeToken for the set element type

130

* @param creator Configuration function for adding bindings to the set

131

*/

132

fun <T : Any> DI.Builder.BindInSet(

133

tag: Any? = null,

134

overrides: Boolean? = null,

135

type: TypeToken<out T>,

136

creator: SetBinder<T>.() -> Unit,

137

)

138

139

/**

140

* Add bindings to an existing set binding

141

* @param tag Optional tag for the set binding to add to

142

* @param overrides Whether added bindings may override existing bindings

143

* @param type TypeToken for the set element type

144

* @param creator Configuration function for adding bindings to the set

145

*/

146

fun <T : Any> DI.Builder.InBindSet(

147

tag: Any? = null,

148

overrides: Boolean? = null,

149

type: TypeToken<out T>,

150

creator: SetBinder<T>.() -> Unit,

151

)

152

153

/**

154

* Create a new argument set binding for factory collections

155

* @param tag Optional tag for the set binding

156

* @param overrides Whether this set binding may override existing bindings

157

* @param argType TypeToken for the factory argument type

158

* @param type TypeToken for the factory return type

159

* @param creator Configuration function for adding factory bindings to the set

160

*/

161

fun <A : Any, T : Any> DI.Builder.BindInArgSet(

162

tag: Any? = null,

163

overrides: Boolean? = null,

164

argType: TypeToken<in A>,

165

type: TypeToken<out T>,

166

creator: ArgSetBinder<A, T>.() -> Unit,

167

)

168

169

/**

170

* Add factory bindings to an existing argument set binding

171

* @param tag Optional tag for the set binding to add to

172

* @param overrides Whether added bindings may override existing bindings

173

* @param argType TypeToken for the factory argument type

174

* @param type TypeToken for the factory return type

175

* @param creator Configuration function for adding factory bindings to the set

176

*/

177

fun <A : Any, T : Any> DI.Builder.InBindArgSet(

178

tag: Any? = null,

179

overrides: Boolean? = null,

180

argType: TypeToken<in A>,

181

type: TypeToken<out T>,

182

creator: ArgSetBinder<A, T>.() -> Unit,

183

)

184

185

/**

186

* Add a single binding to an existing set binding

187

* @param tag Optional tag for the set binding to add to

188

* @param overrides Whether this binding may override existing bindings

189

* @param binding The binding to add to the set

190

*/

191

fun <T : Any> DI.Builder.AddBindInSet(

192

tag: Any? = null,

193

overrides: Boolean? = null,

194

binding: DIBinding<*, *, T>,

195

)

196

```

197

198

### Constructor Injection Binding Methods

199

200

Convenience methods for binding types using their constructors with automatic dependency injection. These methods support up to 22 constructor parameters and automatically resolve dependencies for each parameter.

201

202

```kotlin { .api }

203

/**

204

* Bind a singleton using constructor injection (0-22 parameters)

205

* @param constructor Constructor function reference (e.g., ::MyClass)

206

* @param tag Optional tag for the binding

207

* @param overrides Whether this binding may override existing bindings

208

* @param sync Whether the singleton creation should be synchronized

209

*/

210

fun <T : Any> DI.Builder.bindSingletonOf(

211

crossinline constructor: () -> T,

212

tag: Any? = null,

213

overrides: Boolean? = null,

214

sync: Boolean = true,

215

): Unit

216

217

fun <T : Any, P1> DI.Builder.bindSingletonOf(

218

crossinline constructor: (P1) -> T,

219

tag: Any? = null,

220

overrides: Boolean? = null,

221

sync: Boolean = true,

222

): Unit

223

224

fun <T : Any, P1, P2> DI.Builder.bindSingletonOf(

225

crossinline constructor: (P1, P2) -> T,

226

tag: Any? = null,

227

overrides: Boolean? = null,

228

sync: Boolean = true,

229

): Unit

230

231

fun <T : Any, P1, P2, P3> DI.Builder.bindSingletonOf(

232

crossinline constructor: (P1, P2, P3) -> T,

233

tag: Any? = null,

234

overrides: Boolean? = null,

235

sync: Boolean = true,

236

): Unit

237

// ... continues up to 22 parameters

238

239

/**

240

* Bind a provider using constructor injection (0-22 parameters)

241

* @param constructor Constructor function reference (e.g., ::MyClass)

242

* @param tag Optional tag for the binding

243

* @param overrides Whether this binding may override existing bindings

244

*/

245

fun <T : Any> DI.Builder.bindProviderOf(

246

crossinline constructor: () -> T,

247

tag: Any? = null,

248

overrides: Boolean? = null,

249

): Unit

250

251

fun <T : Any, P1> DI.Builder.bindProviderOf(

252

crossinline constructor: (P1) -> T,

253

tag: Any? = null,

254

overrides: Boolean? = null,

255

): Unit

256

257

fun <T : Any, P1, P2> DI.Builder.bindProviderOf(

258

crossinline constructor: (P1, P2) -> T,

259

tag: Any? = null,

260

overrides: Boolean? = null,

261

): Unit

262

263

fun <T : Any, P1, P2, P3> DI.Builder.bindProviderOf(

264

crossinline constructor: (P1, P2, P3) -> T,

265

tag: Any? = null,

266

overrides: Boolean? = null,

267

): Unit

268

// ... continues up to 22 parameters

269

270

/**

271

* Bind an eager singleton using constructor injection (0-22 parameters)

272

* @param constructor Constructor function reference (e.g., ::MyClass)

273

* @param tag Optional tag for the binding

274

* @param overrides Whether this binding may override existing bindings

275

*/

276

fun <T : Any> DI.Builder.bindEagerSingletonOf(

277

crossinline constructor: () -> T,

278

tag: Any? = null,

279

overrides: Boolean? = null,

280

): Unit

281

282

fun <T : Any, P1> DI.Builder.bindEagerSingletonOf(

283

crossinline constructor: (P1) -> T,

284

tag: Any? = null,

285

overrides: Boolean? = null,

286

): Unit

287

// ... continues up to 22 parameters

288

```

289

290

**Usage Examples:**

291

292

```kotlin

293

import org.kodein.di.*

294

295

class DatabaseConfig(val url: String, val maxConnections: Int)

296

class DatabaseService(private val config: DatabaseConfig)

297

class UserRepository(private val db: DatabaseService, private val logger: Logger)

298

class UserService(private val repository: UserRepository, private val validator: UserValidator)

299

300

val di = DI {

301

// Bind configuration

302

bindInstance<DatabaseConfig> { DatabaseConfig("jdbc:h2:mem:test", 10) }

303

bindInstance<Logger> { ConsoleLogger() }

304

305

// Use constructor injection - dependencies automatically resolved

306

bindSingletonOf(::DatabaseService) // Injects DatabaseConfig

307

bindSingletonOf(::UserRepository) // Injects DatabaseService and Logger

308

bindProviderOf(::UserValidator) // Creates new validator instances

309

bindSingletonOf(::UserService) // Injects UserRepository and UserValidator

310

}

311

```

312

313

### Factory Bindings

314

315

Factory bindings create new instances each time they are requested, accepting an argument to customize the created instance.

316

317

```kotlin { .api }

318

/**

319

* Factory binding that takes an argument and returns a new instance

320

* @param C Context type for scoped bindings

321

* @param A Argument type for the factory function

322

* @param T Return type of the created instances

323

*/

324

class Factory<C : Any, A, T : Any> : DIBinding<C, A, T>

325

326

/**

327

* Create a factory binding within a BindBuilder context

328

* @param creator Function that creates instances from arguments

329

* @return Factory binding instance

330

*/

331

fun <A, T : Any> DI.BindBuilder<*>.factory(

332

creator: BindingDI<*>.(A) -> T

333

): Factory<*, A, T>

334

335

/**

336

* Directly bind a factory with convenience method

337

* @param tag Optional tag for the binding

338

* @param overrides Whether this binding may override existing bindings

339

* @param creator Function that creates instances from arguments

340

*/

341

fun <A, T : Any> DI.Builder.bindFactory(

342

tag: Any? = null,

343

overrides: Boolean? = null,

344

creator: DirectDI.(A) -> T

345

)

346

```

347

348

### Provider Bindings

349

350

Provider bindings create new instances each time they are requested, taking no arguments (no-argument factories).

351

352

```kotlin { .api }

353

/**

354

* Provider binding that creates new instances without arguments

355

* @param C Context type for scoped bindings

356

* @param T Return type of the created instances

357

*/

358

class Provider<C : Any, T : Any> : DIBinding<C, Unit, T>

359

360

/**

361

* Create a provider binding within a BindBuilder context

362

* @param creator Function that creates instances

363

* @return Provider binding instance

364

*/

365

fun <T : Any> DI.BindBuilder<*>.provider(

366

creator: NoArgBindingDI<*>.() -> T

367

): Provider<*, T>

368

369

/**

370

* Directly bind a provider with convenience method

371

* @param tag Optional tag for the binding

372

* @param overrides Whether this binding may override existing bindings

373

* @param creator Function that creates instances

374

*/

375

fun <T : Any> DI.Builder.bindProvider(

376

tag: Any? = null,

377

overrides: Boolean? = null,

378

creator: DirectDI.() -> T

379

)

380

381

/**

382

* Bind a provider using constructor injection (up to 22 parameters)

383

* @param constructor Constructor function reference

384

* @param tag Optional tag for the binding

385

* @param overrides Whether this binding may override existing bindings

386

*/

387

fun <T : Any> DI.Builder.bindProviderOf(

388

constructor: () -> T,

389

tag: Any? = null,

390

overrides: Boolean? = null

391

)

392

393

fun <P1, T : Any> DI.Builder.bindProviderOf(

394

constructor: (P1) -> T,

395

tag: Any? = null,

396

overrides: Boolean? = null

397

)

398

399

// ... up to 22 parameter overloads

400

```

401

402

### Singleton Bindings

403

404

Singleton bindings create one instance per scope and reuse it for all subsequent requests within that scope.

405

406

```kotlin { .api }

407

/**

408

* Singleton binding that creates one instance per scope

409

* @param C Context type for the scoped singleton

410

* @param T Return type of the singleton instance

411

*/

412

class Singleton<C : Any, T : Any> : DIBinding<C, Unit, T>

413

414

/**

415

* Create a singleton binding within a scoped BindBuilder context

416

* @param ref Reference type for instance storage (default, thread-local, etc.)

417

* @param sync Whether to synchronize access to the singleton

418

* @param creator Function that creates the singleton instance

419

* @return Singleton binding instance

420

*/

421

fun <T : Any> DI.BindBuilder.WithScope<*>.singleton(

422

ref: RefMaker = SingletonReference,

423

sync: Boolean = true,

424

creator: NoArgBindingDI<*>.() -> T

425

): Singleton<*, T>

426

427

/**

428

* Directly bind a singleton with convenience method

429

* @param tag Optional tag for the binding

430

* @param overrides Whether this binding may override existing bindings

431

* @param sync Whether to synchronize access to the singleton

432

* @param creator Function that creates the singleton instance

433

*/

434

fun <T : Any> DI.Builder.bindSingleton(

435

tag: Any? = null,

436

overrides: Boolean? = null,

437

sync: Boolean = true,

438

creator: DirectDI.() -> T

439

)

440

441

/**

442

* Bind a singleton using constructor injection (up to 22 parameters)

443

* @param constructor Constructor function reference

444

* @param tag Optional tag for the binding

445

* @param overrides Whether this binding may override existing bindings

446

* @param sync Whether to synchronize access to the singleton

447

*/

448

fun <T : Any> DI.Builder.bindSingletonOf(

449

constructor: () -> T,

450

tag: Any? = null,

451

overrides: Boolean? = null,

452

sync: Boolean = true

453

)

454

455

// ... up to 22 parameter overloads

456

```

457

458

### Eager Singleton Bindings

459

460

Eager singleton bindings create their instance immediately when the DI container is built, not on first access.

461

462

```kotlin { .api }

463

/**

464

* Eager singleton that is created when the DI container is built

465

* @param T Return type of the eager singleton instance

466

*/

467

class EagerSingleton<T : Any> : DIBinding<Any, Unit, T>

468

469

/**

470

* Create an eager singleton binding

471

* @param creator Function that creates the instance immediately

472

* @return EagerSingleton binding instance

473

*/

474

fun <T : Any> DI.Builder.eagerSingleton(

475

creator: DirectDI.() -> T

476

): EagerSingleton<T>

477

478

/**

479

* Directly bind an eager singleton with convenience method

480

* @param tag Optional tag for the binding

481

* @param overrides Whether this binding may override existing bindings

482

* @param creator Function that creates the instance immediately

483

*/

484

fun <T : Any> DI.Builder.bindEagerSingleton(

485

tag: Any? = null,

486

overrides: Boolean? = null,

487

creator: DirectDI.() -> T

488

)

489

```

490

491

### Instance Bindings

492

493

Instance bindings store pre-created objects in the DI container for later retrieval.

494

495

```kotlin { .api }

496

/**

497

* Instance binding that stores a pre-created object

498

* @param T Type of the stored instance

499

*/

500

class InstanceBinding<T : Any> : DIBinding<Any, Unit, T>

501

502

/**

503

* Create an instance binding from a pre-created object

504

* @param instance The pre-created instance to store

505

* @return InstanceBinding that returns the stored instance

506

*/

507

fun <T : Any> DI.Builder.instance(instance: T): InstanceBinding<T>

508

509

/**

510

* Directly bind an instance with convenience method

511

* @param tag Optional tag for the binding

512

* @param overrides Whether this binding may override existing bindings

513

* @param creator Function that provides the instance to store

514

*/

515

fun <T : Any> DI.Builder.bindInstance(

516

tag: Any? = null,

517

overrides: Boolean? = null,

518

creator: () -> T

519

)

520

521

/**

522

* Bind a constant value (alias for bindInstance)

523

* @param tag Optional tag for the binding

524

* @param overrides Whether this binding may override existing bindings

525

* @param creator Function that provides the constant value

526

*/

527

fun <T : Any> DI.Builder.bindConstant(

528

tag: Any? = null,

529

overrides: Boolean? = null,

530

creator: () -> T

531

)

532

```

533

534

### Multiton Bindings

535

536

Multiton bindings create one instance per unique argument value, combining aspects of factory and singleton patterns.

537

538

```kotlin { .api }

539

/**

540

* Multiton binding that creates one instance per unique argument

541

* @param C Context type for scoped multitons

542

* @param A Argument type used as the multiton key

543

* @param T Return type of the multiton instances

544

*/

545

class Multiton<C : Any, A, T : Any> : DIBinding<C, A, T>

546

547

/**

548

* Create a multiton binding within a scoped BindBuilder context

549

* @param ref Reference type for instance storage

550

* @param sync Whether to synchronize access to multiton instances

551

* @param creator Function that creates instances for each unique argument

552

* @return Multiton binding instance

553

*/

554

fun <A, T : Any> DI.BindBuilder.WithScope<*>.multiton(

555

ref: RefMaker = MultitonReference,

556

sync: Boolean = true,

557

creator: BindingDI<*>.(A) -> T

558

): Multiton<*, A, T>

559

560

/**

561

* Directly bind a multiton with convenience method

562

* @param tag Optional tag for the binding

563

* @param overrides Whether this binding may override existing bindings

564

* @param sync Whether to synchronize access to multiton instances

565

* @param creator Function that creates instances for each unique argument

566

*/

567

fun <A, T : Any> DI.Builder.bindMultiton(

568

tag: Any? = null,

569

overrides: Boolean? = null,

570

sync: Boolean = true,

571

creator: DirectDI.(A) -> T

572

)

573

```

574

575

### Set Bindings

576

577

Set bindings allow multiple bindings for the same type, collecting them into a Set for retrieval.

578

579

```kotlin { .api }

580

/**

581

* Create a set binding and add elements to it

582

* @param tag Optional tag for the set binding

583

* @param overrides Whether this binding may override existing bindings

584

* @param type TypeToken for the set element type

585

* @param creator Block that adds bindings to the set

586

*/

587

fun <T : Any> DI.Builder.BindInSet(

588

tag: Any? = null,

589

overrides: Boolean? = null,

590

type: TypeToken<out T>,

591

creator: SetBinder<T>.() -> Unit

592

)

593

594

/**

595

* Add elements to an existing set binding

596

* @param tag Optional tag for the set binding

597

* @param overrides Whether this addition may override existing elements

598

* @param type TypeToken for the set element type

599

* @param creator Block that adds bindings to the set

600

*/

601

fun <T : Any> DI.Builder.InBindSet(

602

tag: Any? = null,

603

overrides: Boolean? = null,

604

type: TypeToken<out T>,

605

creator: SetBinder<T>.() -> Unit

606

)

607

608

/**

609

* Add a single binding to a set

610

* @param tag Optional tag for the set binding

611

* @param overrides Whether this addition may override existing elements

612

* @param binding The binding to add to the set

613

*/

614

fun <T : Any> DI.Builder.AddBindInSet(

615

tag: Any? = null,

616

overrides: Boolean? = null,

617

binding: DIBinding<*, *, T>

618

)

619

620

/**

621

* Set binder for adding multiple bindings to a set

622

*/

623

interface DI.Builder.SetBinder<T : Any> {

624

/**

625

* Add a binding to the set

626

* @param createBinding Function that creates the binding to add

627

*/

628

fun add(createBinding: () -> DIBinding<*, *, out T>)

629

630

/**

631

* Add a binding to both the set and the DI container

632

* @param tag Optional tag for the binding

633

* @param overrides Whether this binding may override existing bindings

634

* @param createBinding Function that creates the binding to add

635

*/

636

fun bind(

637

tag: Any? = null,

638

overrides: Boolean? = null,

639

createBinding: () -> DIBinding<*, *, out T>

640

)

641

}

642

```

643

644

**Usage Examples:**

645

646

```kotlin

647

val di = DI {

648

// Factory binding - new instance each time with argument

649

bind<UserRepository>() with factory { userId: String ->

650

UserRepositoryImpl(userId, instance())

651

}

652

653

// Provider binding - new instance each time, no arguments

654

bind<EmailService>() with provider {

655

EmailServiceImpl(instance(), instance())

656

}

657

658

// Singleton binding - one instance per container

659

bind<Database>() with singleton {

660

DatabaseImpl(constant("connectionString"))

661

}

662

663

// Eager singleton - created immediately when DI is built

664

bind<ConfigService>() with eagerSingleton {

665

ConfigServiceImpl().also { it.initialize() }

666

}

667

668

// Instance binding - pre-created object

669

bind<AppConfig>() with instance(AppConfig(debug = true))

670

671

// Multiton binding - one instance per unique argument

672

bind<Cache>() with multiton { cacheKey: String ->

673

InMemoryCache(cacheKey, instance())

674

}

675

676

// Constant binding with tag

677

constant("apiUrl") with "https://api.example.com"

678

constant("timeout") with 30_000L

679

680

// Set binding - multiple implementations

681

bindInSet<Plugin> {

682

add { provider { LoggingPlugin() } }

683

add { provider { MetricsPlugin() } }

684

add { provider { SecurityPlugin() } }

685

}

686

687

// Constructor injection with bindProviderOf

688

bindProviderOf(::UserServiceImpl) // Automatically injects constructor parameters

689

bindSingletonOf(::DatabaseConnectionPool)

690

691

// Using overrides

692

bind<Logger>(overrides = true) with singleton {

693

if (constant<Boolean>("debug")) ConsoleLogger() else FileLogger()

694

}

695

}

696

697

// Usage in classes

698

class UserController : DIAware {

699

override val di = di

700

701

private val userRepo: UserRepository by factory()

702

private val emailService: EmailService by provider()

703

private val database: Database by instance()

704

private val plugins: Set<Plugin> by instance()

705

706

fun createUser(userId: String) {

707

val repo = userRepo(userId) // Factory with argument

708

val email = emailService() // Provider creates new instance

709

// database is singleton, same instance each time

710

}

711

}

712

```