koin
koin copied to clipboard
Simplify binding of interface to a concrete implementation using Extended DSL
Is your feature request related to a problem? Please describe. Define an instance of the parametrized class using
In koin 3.2.0 it is possible to bind an interface to concrete implementation like this:
single<AlbumRepository> { AlbumRepositoryImpl(get(), get()) }
Describe the solution you'd like
I wonder if type Kotlin type system would allow simplifying the above syntax to...
singleOf<AlbumRepository>(::AlbumRepositoryImpl)
...so there is no need to explicitly pass params
This is reified version of what is already possible:
single { GetAlbumUseCase(get()) }
singleOf(::GetAlbumUseCase) // no need to explicitly pass params
Target Koin project https://github.com/igorwojda/android-showcase
Hello,
yes. I will check to help make it better and allow kind of writing as you mention 👍
@igorwojda The API already allows such direct binding:
val koin = koinApplication {
modules(module {
singleOf<IClassA>(::ClassA)
})
}.koin
assertNotNull(koin.getOrNull<IClassA>())
assertNull(koin.getOrNull<ClassA>())
This is working, but keep in mind that it can't block some configuration checks. The new verify()
API allows checking Koin configuration statically by looking at class constructors. In such "direct binding," we don't know the original class to build from the external point of view.
There is always pros and cons in each part
I can't make this work. At least not with a real life example. As soon as my class has a dependency I get: "None of the following functions can be called with the arguments supplied." and it does not compile anymore. Minimal example:
class ClassA
interface IClassB
class ClassB(private val classA: ClassA): IClassB
val myModule = module {
singleOf(::ClassA)
singleOf<IClassB>(::ClassB) // <-- This line fails with the above-mentioned error
}
Is there a way to resolve this or do I have to use the old-style dsl?
I am having the same problem, please reopen.
same as https://github.com/InsertKoinIO/koin/issues/1598 it's not intended to use the inferred type in "constructor dsl", singleOf, factoryOf ...
You need to use the bind operator like this:
val myModule = module {
singleOf(::ClassA)
singleOf(::ClassB){ bind<IClassB>() }
}
Hello @arnaudgiuliani , Why not add this possibility to "constructor DSL" so as not to record ClassB and IClassB in the module which is not a good practice when using interfaces.
DSL extensions might look like this:
inline fun <reified IR: Any, reified R : IR, reified T1> Module.factoryOf(
inferredType: KClass<IR>,
crossinline constructor: (T1) -> R,
noinline options: DefinitionOptions<IR>? = null
): KoinDefinition<IR> = factory<IR> { new(constructor) }.onOptions(options)
Thanks in advance for you rsponse.
@dbaronne yes, interesting. Need to check how it's possible and how it's interacting with the current DSL