Я хотел бы иметь возможность предоставлять информацию о типе субкомпоненту внутри обобщенного 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>
в нашем основном графе без проблем, как прокомментировано.