Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Override inject binding #468

Open
todoFixIt opened this issue Feb 19, 2025 · 0 comments
Open

Override inject binding #468

todoFixIt opened this issue Feb 19, 2025 · 0 comments

Comments

@todoFixIt
Copy link

Is it possible to override an interface binding bind to a @Inject dependency?

Scenario
A library that exposes a @Component and all its dependencies are declared only with @inject and bindextension for interfaces.

An app that consumes that library and wants to override just one interface so when any @Inject class requiring that interface gets the app impl instead of the one provided by the library.

Lib code

interface SomeInterface {
    fun someFunction()
}

@Inject
class LibsImpl : SomeInterface {
    override fun someFunction() {
        println("lib impl")
    }
}

@Scope
annotation class LibScope

@Component
@LibScope
interface LibComponent {

    val someInterface: SomeInterface
    val LibsImpl.bind: SomeInterface
        @Provides
        get() = this
}

@KmpComponentCreate
expect fun LibComponent.Companion.createKmp(): LibComponent

App code

@Inject
@AppScope
class AppImpl : SomeInterface {
    override fun someFunction() {
        println("app impl")
    }
}

@Scope
annotation class AppScope

@Component
@AppScope
abstract class AppComponent : LibComponent {

// Throws error -> Cannot provide: SomeInterface as it is already provided
//    val AppImpl.bind: SomeInterface
//        @Provides
//        get() = AppImpl()

// Throws error -> Cannot provide: SomeInterface as it is already provided
//    @Provides
//    fun provideAppImpl(): SomeInterface = AppImpl()
}

@KmpComponentCreate
expect fun AppComponent.Companion.createKmp(): AppComponent

Issues

  • Didn't find a way to replace SomeInterface implementation with the AppImpl since the signature for binds is using an extension and you can't override extensions.
  • This doesn't compile because I'm using both AppScope and LibScope but I want to be able to inject classes in my library and made them "singletons" (' LibScope' ) and do the same in the app, I can't just use the library scope, it would be wrong and not possible if I had two libs exposing their components.
  • I've tried composition instead of inheritance but still didn't find a way of overriding SomeInterface, I would be creating new instances instead of overriding it.

Solutions

  • Create @Bind annotation so it could be a normal function and could be overrided on children, also it would be nice to add an optional parameter to the inject annotation @Inject(SomeInterface::class) class SomeImpl for bindings.
  • Currently, unless I missed something, the only thing that I can think of is not using @inject and bind on the library and provide manually each dependency, and then override what I want in the app, but is really missing the @Injectfeature which helps a lot reducing the boilerplate and maintenance time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant