kosi-libs / Kodein

Painless Kotlin Dependency Injection
https://kosi-libs.org/kodein
MIT License
3.21k stars 174 forks source link

Shorthand for trivial singleton declarations #444

Closed CLOVIS-AI closed 1 year ago

CLOVIS-AI commented 1 year ago

Problem

Currently, we often end up with declarations like this:

bind() from singleton { FooService(instance(), instance(), instance()) }
bind() from singleton { BarService(instance(), instance(), instance(), instance(), instance()) }

This is inconvenient, because each time a parameter is added or removed, the DI module declaration fails to compile.

Proposal

Introduce helpers to generate singletons trivially for any number of arguments (per Kotlin tradition, up to 22):

// 1..3
public inline fun <C : Any, reified T: Any> DI.BindBuilder.WithScope<C>.singleton(ref: RefMaker? = null, sync: Boolean = true, noinline creator: (Any) -> T) = singleton { creator(instance()) }
public inline fun <C : Any, reified T: Any> DI.BindBuilder.WithScope<C>.singleton(ref: RefMaker? = null, sync: Boolean = true, noinline creator: (Any, Any) -> T) = singleton { creator(instance(), instance()) }
public inline fun <C : Any, reified T: Any> DI.BindBuilder.WithScope<C>.singleton(ref: RefMaker? = null, sync: Boolean = true, noinline creator: (Any, Any, Any) -> T) = singleton { creator(instance(), instance(), instance()) }

// Usage
bind() from singleton(::FooService)
bind() from singleton(::BarService)

This way, adding or removing arguments does not make the CI module stop compiling.

romainbsl commented 1 year ago

In fact there is already something for this use case. Maybe the documentation is not that easy to find. https://kosi-libs.org/kodein/7.19/core/bindings.html#_transitive_dependencies under the "tips" section.

val di = DI {
    bindSingletonOf(::FooService)
    // OR
    bindProviderOf(::FooService)
}

This is ok for a range from 0 to 10 constructor parameters.

CLOVIS-AI commented 1 year ago

Thanks, that's exactly what I was searching for. Have a good day :)