InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
9k stars 714 forks source link

Multiton #346

Closed BulatMukhutdinov closed 3 weeks ago

BulatMukhutdinov commented 5 years ago

Is it possible to retrieve always the same object given the same argument? Something similar to kodein's multiton? Thanks

arnaudgiuliani commented 5 years ago

Never encountered such concept in other DI solution apart kodein :) Sorry nothing like that in the hat

SpaceBison commented 5 years ago

I managed to get a workaround for this on Koin 1.0.1:

inline fun <reified T : Any> ModuleDefinition.multi(
    name: String = "",
    createOnStart: Boolean = false,
    noinline definition: Definition<T>
): BeanDefinition<T> =
    factory(name, createOnStart) { parameterList ->
        val singletonName = name + parameterList.values.hashCode().toString()

        val beanDefinition = single(singletonName) { definition(parameterList) }

        koinContext
            .instanceRegistry
            .beanRegistry
            .definitions
            .add(beanDefinition)

        get<T>(singletonName)
    }

Basically it creates a factory but instead creating a new instance each time it defines a singleton with a name based on the original name and the parameters.

uenowataru04 commented 1 month ago

Now I'm using this workaround on Koin 3.5.6:

@OptIn(KoinInternalApi::class)
inline fun <reified T> Module.multiton(
    qualifier: Any? = null,
    noinline definition: Definition<T>,
) = factory { params ->
    val id = qualifier.hashCode().toString() + params.values.hashCode().toString()
    val singletonQualifier = named(id)

    val findMapping = {
        this@multiton.mappings.entries.find { it.value.beanDefinition.qualifier == singletonQualifier }
    }

    if (findMapping() == null) {
        this@multiton.single<T>(singletonQualifier) {
            definition(params)
        }

        val mapping = findMapping()!!

        getKoin()
            .instanceRegistry
            .saveMapping(allowOverride = true, mapping = mapping.key, factory = mapping.value)
    }

    val instance: T = get(qualifier = singletonQualifier)
    instance
}

But it may be supported in the near future :)

arnaudgiuliani commented 1 month ago

let's check this again 👍