2 of 5
Bindings
Control how instances are created and shared across your application.
Three lifetimes
| Lifetime | Behavior |
|---|---|
factory | New instance every resolve() call |
singleton | One instance forever (global) |
scoped | One instance per scope |
Binding interfaces to implementations
Use factory or singleton when you need explicit control — typically for binding interfaces to concrete classes:
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:
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:
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.