Можно ли передать информацию о параметрах типа через подкомпонент кинжала? - PullRequest
0 голосов
/ 15 марта 2020

Я хотел бы иметь возможность предоставлять информацию о типе субкомпоненту внутри обобщенного c абстрактного класса. У нас есть abstract class с параметром типа, установленным в подклассе (последний из которых связан с нашим графом), и мы пытаемся передать эту информацию о типе субкомпоненту внутри этого класса. При попытке попытаться присоединить параметр типа к подкомпоненту.

Вот более конкретный пример того, чего я хотел бы достичь:

interface Runner<T> {
    fun run(t: T)
}

data class Data<T>(
    val options: T
)

abstract class AbstractRunner<Options> : Runner<Data<Options>> {

    @Inject
    lateinit var mySubcomponentBuilder: MySubcomponent.Builder<Options>

    // Constructing this relies on dynamicData which must be generated at runtime
    // (hence the subcomponent)
    // @Inject
    // lateinit var subRunner: Runner<Options>

    override fun run(data: Data<Options>) {

        // Some dynamically generated data - we can't use assisted injection as this is injected into other classes in
        // the subgraph.
        val dynamicData = Random.nextInt()

        mySubcomponentBuilder
            .dynamicData(dynamicData)
            .build()
            .subcomponentRunner()
            .run(data.options)
    }
}

// We have other objects with associated Runner implementations;
// we list one for brevity.
object Foo
class MyRunner @Inject constructor() : AbstractRunner<Foo>()
class SubRunner @Inject constructor(s: String) : Runner<Foo> {
    override fun run(t: Foo) {}
}

@Component(modules=[MyModule::class])
interface MyComponent {
    fun runner(): Runner<Data<Foo>>
}

@Module(subcomponents=[MySubcomponent::class])
interface MyModule {
    @Binds
    fun bindMyRunner(runner: MyRunner): Runner<Data<Foo>>
}

// This does not work due to generics being banned on (Sub)Components.
@Subcomponent(modules=[SubModule::class])
interface MySubcomponent<T> {
    // We can't parameterise the method; generics are banned on methods in (Sub)Components.
    fun subcomponentRunner(): Runner<T>

    @Subcomponent.Builder
    interface Builder<U> {
        @BindsInstance
        fun dynamicData(i: Int): Builder<U>
        fun build(): MySubcomponent<U>
    }
}

@Module
object SubModule {
    @Provides
    fun provideString(i: Int) = i.toString()
    @Provides
    fun provideSubRunner(s: String): Runner<Foo> = SubRunner(s)
}

Конечно, это не принимайте:

error: @Subcomponent.Builder types must not have any generic types

Можно ли каким-либо другим способом передать эту информацию? Если бы переменная, связанная с нашим подкомпонентом, не была нужна, мы могли бы просто связать наш subRunner: Runner<Options> в нашем основном графе без проблем, как прокомментировано.

...