使用 Kodein 依赖注入,我不想到处传递 kodein 实例

With Kodein dependency injection, I don't want to pass around kodein instances everywhere

使用 Kodein,我发现我必须传递 kodein 实例或将它们注入模块和 类。但有时我有 类 如此脱节,我希望他们能够发现“一个真正的 Kodein”。由于这是一个服务器端应用程序,而且我只有一个 Kodein 范围,所以应该很容易。我可以创建一个全局对象,例如:

val kodeinGlobal: Kodein = Kodein { ... }

但是当一些模块在不同的项目中重复使用时,这就不起作用了,我们不能轻易地共享这个实例。也许一个单独的模块只是为了保存全局会起作用,但它需要是一个 var 并且我希望它不可更改。

Kodein 能否自行找到一个主要的、顶级的或全局的作用域?

注: 此问题是作者(Self-Answered Questions)特意写下并回答的,以便常见 Kotlin/Kodein 主题的惯用答案出现在 SO 中。

在 Kodein 3.x 中有一个名为 kodein-conf 的新模块可用。这允许您创建一个可修改的 Kodein 实例(只要您在第一次注入完成之前修改它),并且它还包含一个 Kodein 全局实例以供共享使用(如果需要的话)。这与正常的 Kodein 实例相反,后者必须在构造时定义所有绑定并且永远不能修改。

使用预定义的全局就像引用 Kodein.global 一样简单。它与任何可配置的 Kodein 实例一样工作:

Kodein.global.addImport(someModule) // add other modules to it

val something: SomethingCool = Kodein.global.instance() // inject from it

如果你想使自己成为全球:

val kodeinGlobal = ConfigurableKodein()

有关 ConfigurableKodein 的更多信息,请阅读 Kodein 3.x docs for ConfigurableKodein, and about the predefined global instance The God Complex: One True Kodein

作为助手,您可以使用新的 KodeinGlobalAware 接口在 class 中自然访问 Kodein 实例,而无需直接引用全局 Kodein 实例。比如添加这个接口,就可以只调用实例的创建方法,如:

class DefaultSomeService(): SomeService, KodeinGlobalAware {
    val mapper: ObjectMapper = instance()
    // ...
}

或者,如果您有一个案例(例如测试),您希望使用全局实例,除非被特定实例覆盖,您可以执行类似的操作:

class DefaultSomeService(override val kodein: Kodein = Kodein.global): SomeService, KodeinAware {
    val mapper: ObjectMapper = instance()
    // ...
}

它使用 KodeinAware 接口并覆盖其抽象成员变量 kodein 以在 class 中执行相同的透明类型注入,同时默认为 global实例.

如果您只想注入 Kodein,无论是全局实例还是特定实例,请参阅: 作为替代方案。