Kodein icon indicating copy to clipboard operation
Kodein copied to clipboard

From documentation, just passing in a DI object to a class that implements DIAware doesn't keep context

Open chrislo27 opened this issue 6 months ago • 0 comments

This is a question regarding with what I've read in the guide and not a bug with Kodein.

In the Retrieval section (https://kosi-libs.org/kodein/7.22/getting-started.html#_retrieval), there's a simple example of using the DIAware interface:

class Presenter(override val di: DI): DIAware {
    private val db: Database by instance()
    private val rnd: Random by instance()
}

This has worked great for my usecases so far. However, I started using the context system in this sort of fashion:

// As an example, di is initialized earlier with:
bind<Thing> { contexted<MyContext>().provider { context.getThing() } }

class ThingUser(override val di: DI) : DIAware {
  val theThing by instance<Thing>()
}

val diWithContext = di.on(context = MyContext())
ThingUser(diWithContext)

If ThingUser attempts to access its theThing, you'll get an exception similar to: org.kodein.di.DI$NotFoundException: No binding found for Thing on context ThingUser

This isn't super obvious as to why. However, since DI also extends DIAware, just passing in and overriding the di in ThingUser isn't enough to carry the context through. Instead I found that changing the signature of the class resolves the issue:

class ThingUser(di: DI) : DIAware by di

which uses the delegate implementation feature in Kotlin. You can still selectively override DIAware properties in ThingUser if needed.


My question is: is this pattern recommended? Since it also handles the context and trigger, I feel like this seems like the right way to do this rather than just overriding di for DIAware per the guide.

If this seems expected I'd be happy to help update the documentation to add a snippet regarding this.

chrislo27 avatar Aug 05 '24 17:08 chrislo27