2 of 5

Bindings

Control how instances are created and shared across your application.

Three lifetimes

LifetimeBehavior
factoryNew instance every resolve() call
singletonOne instance forever (global)
scopedOne instance per scope

Binding interfaces to implementations

Use factory or singleton when you need explicit control — typically for binding interfaces to concrete classes:

kotlin
val container = Container()

// New instance every time
container.factory<PaymentGateway> { StripeGateway() }

// Shared instance (created once, reused)
container.singleton<NotificationService> { SlackNotificationService() }

Auto-resolved registration

For concrete classes that just need a specific lifetime, skip the lambda entirely. The container auto-resolves the constructor dependencies:

kotlin
container.singleton<TenantService>()
container.singleton<CalendarService>()
container.scoped<RequestContext>()
container.factory<TempProcessor>()

// Equivalent to:
container.singleton<TenantService> { resolve() }

Using resolve() inside lambdas

Inside registration lambdas, resolve<T>() is available to reference other bindings. This is useful when one binding depends on another, or when the same implementation backs multiple interfaces:

kotlin
container.singleton<EventBus> { EventBus(this) }
container.singleton<Emitter> { resolve<EventBus>() }
container.singleton<Subscriber> { resolve<EventBus>() }

this refers to the container itself, so you can pass it directly to classes that need it. resolve<T>() pulls from the container's registry, letting you wire shared instances across multiple interface bindings.

Next steps

Learn how scopes give you per-context instance management with automatic cleanup.