amzn / kotlin-inject-anvil

Extensions for the kotlin-inject dependency injection framework
Apache License 2.0
271 stars 8 forks source link

How do you inject subcomponent factory #49

Closed matejdro closed 4 weeks ago

matejdro commented 1 month ago

Maybe a bit stupid question, but I've been trying to figure out how to actually inject the factory into something to instantiate the subcomponent:

@Component
@MergeComponent(AppScope::class)
@SingleIn(AppScope::class)
interface AppComponent : AppComponentMerged {
    fun provideRendererUsage(): RendererUsage
}

@ContributesSubcomponent(LoggedInScope::class)
@SingleIn(LoggedInScope::class)
interface RendererComponent {

    @ContributesSubcomponent.Factory(AppScope::class)
    interface Factory {
        fun createRendererComponent(argument: String): RendererComponent
    }
}

Inject
class RendererUsage(rendererComponentFactory: RendererComponent.Factory)

But above fails with Cannot find an @Inject constructor or provider for: RendererComponent.Factory

vRallev commented 1 month ago

AppComponent will implement the Factory interface. You cannot inject components themselves, therefore you cannot inject Factory. Simply take the AppComponent and call the createRendererComponent() function on it.

matejdro commented 1 month ago

That kinda breaks the non-centralised nature of Anvil, since you still need access to the component instance to create subcomponents.

Is this a fault of kotlin-inject-anvil or kotlin-inject?

vRallev commented 1 month ago

kotlin-inject, but it's the same in Dagger. You need the reference to the component for the parent-child relationship of the components. There's no way around it. Think of the @Factory annotation the same way as a @ContributesTo annotation.

matejdro commented 1 month ago

Doh, the solution is just to add a @Provides function to your main component, that points to itself, which allows injection of it anywhere.

   @Provides
   fun provideRendererSubcomponentFactory(): RendererComponent.Factory = this

do you think it would be a good idea to add this to the README? I can make a PR if necessary.

but it's the same in Dagger

I'm pretty sure that with Dagger's Anvil, you can directly inject subcomponent factories.

vRallev commented 1 month ago

To be honest, I never tried this 🙃 Instead of updating the README, this function should be generated.

matejdro commented 3 weeks ago

Thank you!