<@U0BLRBFMM> I have: ``` bind&lt;ProgressNotifi...
# kodein
d
@salomonbrys I have:
Copy code
bind<ProgressNotifier>() with factory { id: Int, iconRes: Int, title: String ->
        ProgressNotifierImpl(instance(), id, iconRes, title)
    }

    bind() from singleton { InstallationNotifier(factory() as ((Int,Int,String) -> ProgressNotifier)) }
But idea tells me that type inference failed for
A
on
factory()
call in the
InstallationNotifier
constructor... how could I acheive this? the constructor takes:
val progressNotifierFactory: (id: Int, iconRes: Int, title: String) -> ProgressNotifier
a
@dave08 you need to tell
factory
what type of Factory you want, try
InstallationNotifier(factory<(Int, Int, String) -> ProgressNotifier>())
or maybe it could work without any type annotations
InstallationNotifier(factory())
d
I tried that πŸ€’
a
both ways?
d
Yup
a
neither of them worked?
d
nope
a
what are the error messages? still unresolved type?
d
Type inference failed. Expected type mismatch: required: (Int, Int, String) -> ProgressNotifier found: (???) -> ???
That's for factory() by itself
For factory<((Int, Int, String) -> ProgressNotifier)>()
I get:
a
wait a second
d
that it needs two type arguments like
inline fun <reified A, reified T : Any> DKodein.factory(tag: Any? = null)
a
a Factory binding requires you to have a single argument: "This binds a type to a factory function, which is a function that takes an argument of a defined type and that returns an object of the bound type (eg. (A) β†’ T)" http://kodein.org/Kodein-DI/?5.0/core#_factory_binding
d
But a factory can have many arguments... I think the first one is Multi3 type in my case, but when I tried that, I had even more problems...
Kodein...
inline fun <C, reified A1, reified A2, reified A3, reified T: Any> Kodein.BindBuilder.WithContext<C>.factory(noinline creator: BindingKodein<C>.(A1, A2, A3) -> T)
a
alright, one thing you could try is
factory<Multi3<Int, Int, String>, ProgressNotifier>()
d
Thanks for hanging in there! But no go... I got Multi3<Int, Int, String>(...) expected. Type mismatch. Required: (Int, Int, String) -> ProgressNotifier Found Multi3<Int, Int, String>
a
hm, then I'm out of guesses
As a workaround you could use a
data class
instead of 3 arguments
d
Funny no? Thanks anyways for all the help πŸ˜‰! Maybe @salomonbrys might know, or maybe this is a bug...
s
OK, so multi-argument factories are in fact... a scam πŸ˜‰
d
πŸ€”
s
A multi-argument factory is in fact a factory that takes a
MultiX
argument
So, you should try
factory() as (Multi3<Int,Int,String>) -> ProgressNotifier
Or, if you want to set the
factory
function parameters, you need to give all parameters (the argument and the return type) : `factory<Multi3<Int,Int,String>,ProgressNotifier>()
d
Still no go, since my constructor takes (Int, Int, String) -> ProgressNotifier, and you're passing it a Multi... meaning I'd have to define the constructor to depend on Kodein... pretty big no no...
s
OK, give me a second πŸ˜‰
@dave08 You're using generic or erased ?
d
generic
s
Add this to your project :
Copy code
import org.kodein.di.*

inline fun <reified A1, reified A2, reified A3, reified T : Any> DKodein.factory3(tag: Any? = null): ((A1, A2, A3) -> T) {
    val f = Factory<Multi3<A1, A2, A3>, T>(generic(), generic(), tag)
    return { a1, a2, a3 -> f(Multi3(a1, a2, a3, generic())) }
}
Then this should work :
bind() from singleton { InstallationNotifier(factory3()) }
I'll add these function for
Kodein
as well as
DKodein
and for 2 to 5 parameters in next release πŸ˜‰
I hadn't thought of this use case
d
Nope:
Copy code
Process: com.lomdaat.coreservices.kosherstore, PID: 27116
    java.lang.ClassCastException: libcore.reflect.TypeVariableImpl cannot be cast to java.lang.Class
        at org.kodein.di.ParameterizedTypeToken.getRawType(types.kt:177)
        at org.kodein.di.ParameterizedTypeToken.getRaw(types.kt:202)
        at org.kodein.di.TypeToken$DefaultImpls.isAssignableFrom(typeToken.kt:82)
        at org.kodein.di.JVMTypeToken.isAssignableFrom(types.kt:143)
        at org.kodein.di.ClassTypeToken.isAssignableFrom(types.kt:302)
        at org.kodein.di.TypeToken$DefaultImpls.isAssignableFrom(typeToken.kt:89)
        at org.kodein.di.JVMTypeToken.isAssignableFrom(types.kt:143)
        at org.kodein.di.internal.TypeChecker$Down.check(KodeinTreeImpl.kt:12)
        at org.kodein.di.internal.KodeinTreeImpl$findBySpecs$3.invoke(KodeinTreeImpl.kt:71)
        at org.kodein.di.internal.KodeinTreeImpl$findBySpecs$3.invoke(KodeinTreeImpl.kt:28)
        at kotlin.sequences.FilteringSequence$iterator$1.calcNext(Sequences.kt:110)
        at kotlin.sequences.FilteringSequence$iterator$1.hasNext(Sequences.kt:133)
        at kotlin.sequences.FlatteningSequence$iterator$1.ensureItemIterator(Sequences.kt:249)
        at kotlin.sequences.FlatteningSequence$iterator$1.hasNext(Sequences.kt:241)
        at kotlin.sequences.FilteringSequence$iterator$1.calcNext(Sequences.kt:108)
        at kotlin.sequences.FilteringSequence$iterator$1.hasNext(Sequences.kt:133)
        at kotlin.sequences.TransformingSequence$iterator$1.hasNext(Sequences.kt:153)
        at kotlin.sequences.SequencesKt___SequencesKt.toCollection(_Sequences.kt:654)
        at kotlin.sequences.SequencesKt___SequencesKt.toMutableList(_Sequences.kt:684)
        at kotlin.sequences.SequencesKt___SequencesKt.toList(_Sequences.kt:675)
        at org.kodein.di.internal.KodeinTreeImpl.findBySpecs(KodeinTreeImpl.kt:81)
        at org.kodein.di.internal.KodeinTreeImpl.find(KodeinTreeImpl.kt:99)
        at org.kodein.di.KodeinTree$DefaultImpls.find$default(KodeinTree.kt:32)
        at org.kodein.di.internal.KodeinContainerImpl.factory(KodeinContainerImpl.kt:146)
        at org.kodein.di.KodeinContainer$DefaultImpls.factory$default(KodeinContainer.kt:33)
        at org.kodein.di.internal.DKodeinBaseImpl.Factory(DKodeinImpl.kt:21)
        at org.kodein.di.internal.BindingKodeinImpl.Factory(KodeinImpl.kt)
        at org.kodein.di.bindings.BindingKodeinContextWrap.Factory(standardBindings.kt)
        at org.kodein.di.bindings.NoArgBindingKodeinWrap.Factory(BindingKodein.kt)
It compiles, but crashes on Android device...
s
OK, I'm at a conf, I'll handle this as soon as I can πŸ˜‰
d
Thanks! Let me know.. simple smile
@salomonbrys Any news on this?
s
This is a limitation of reified generics:
Copy code
inline fun <reified A1, reified A2, reified A3> multi3Generic() = generic<Multi3<A1, A2, A3>>()

fun main(args: Array<String>) {

    println(generic<Multi3<String, String, Int>>().simpleDispString())
    // Multi3<String, String, Int>
    
    println(multi3Generic<String, String, Int>().simpleDispString())
    // Multi3<A1, A2, A3>
}
So, this is looks quite complicated to fix, if fixable at all.
Right now, I would advise you to use a data class
I'll investigate more when I have time πŸ˜‰
d
So with one param it'll work? I guess I'll have to do that, thanks for looking into this anyways. πŸ‘πŸΌ
πŸ‘Œ 1