InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
9.12k stars 721 forks source link

Constructor DSL `named()` doesn't create qualifier and therefore doesn't work #1762

Open timplifier opened 10 months ago

timplifier commented 10 months ago

Describe the bug When you want to use Constructor DSL to create your definitions and use named() function to provide a string qualifier to the definition, it doesn't work and your app crash. However, using standard DSL, everything works just fine and as expected.

To Reproduce Steps to reproduce the behavior:

  1. Create some definition using Constructor DSL
  2. In definition scope, add named() function with supplied qualifier
  3. Request this definition with qualifier
  4. See error

Expected behavior Should work as standard DSL and don't crash

Koin module and version: koin-core:3.5.3

Snippet or Sample project to help reproduce

This will not work

private fun generateOkHttpClientWithoutAuthorization() =
    OkHttpClient.Builder().connectTimeout(120, TimeUnit.SECONDS).readTimeout(120, TimeUnit.SECONDS)
        .writeTimeout(120, TimeUnit.SECONDS).addInterceptor(
            HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
        ).build()

private fun generateRetrofit(gson: Gson, client: OkHttpClient): Retrofit {
    return Retrofit.Builder().client(client).addConverterFactory(GsonConverterFactory.create(gson))
        .baseUrl(BuildConfig.BASE_URL).build()
}

val coreDataModule = module {

    singleOf(::generateOkHttpClientWithoutAuthorization) {
        named("Non-Authenticated")
    }

    singleOf(::generateGson)

    single(named("NoAuthentication")) {
        generateRetrofit(
            gson = get(),
            client = get(named("Non-Authenticated"))
        )
    }
}

class AuthenticationNetworkClient(
    val retrofit: Retrofit
)

val authenticationDataModule = module {
    includes(coreDataModule)
    single { AuthenticationNetworkClient(get(named("NoAuthentication"))) }
}

This will

private fun generateOkHttpClientWithoutAuthorization() =
    OkHttpClient.Builder().connectTimeout(120, TimeUnit.SECONDS).readTimeout(120, TimeUnit.SECONDS)
        .writeTimeout(120, TimeUnit.SECONDS).addInterceptor(
            HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
        ).build()

private fun generateRetrofit(gson: Gson, client: OkHttpClient): Retrofit {
    return Retrofit.Builder().client(client).addConverterFactory(GsonConverterFactory.create(gson))
        .baseUrl(BuildConfig.BASE_URL).build()
}

val coreDataModule = module {
        single(named("Non-Authenticated")) { generateOkHttpClientWithoutAuthorization() }

        singleOf(::generateGson)

    single(named("NoAuthentication")) {
        generateRetrofit(
            gson = get(),
            client = get(named("Non-Authenticated"))
        )
    }
}

class AuthenticationNetworkClient(
    val retrofit: Retrofit
)
val authenticationDataModule = module {
    includes(coreDataModule)
    single { AuthenticationNetworkClient(get(named("NoAuthentication"))) }
}
siralam commented 10 months ago

Having the same issue 🙌

arnaudgiuliani commented 10 months ago

I would say there is a mix between 2 APIs that are the same :/

arnaudgiuliani commented 3 months ago

Ok, this will follow DSL refactoring to help in 4.1