使用Kodein,我发现我必须传递kodein实例或将它们注入模块和类中。但有时候我的课程如此断开,我希望他们能够发现“一个真正的Kodein”。由于这是一个服务器端应用程序,而且我只有一个Kodein范围,因此应该很容易。我可以创建一个全局对象,例如:
val kodeinGlobal: Kodein = Kodein { ... }
但是,当某些模块在不同项目中重复使用时,这不起作用,我们无法轻松共享这一个实例。也许一个单独的模块只是为了保持全局可行,但那么它需要是var
,我宁愿它不可更改。
Kodein可以自己找到主要,顶级或全球范围吗?
注意: 这个问题是由作者(Self-Answered Questions)故意编写和回答的,因此对于常见问题Kotlin的惯用答案/ Kodein主题出现在SO中。
答案 0 :(得分:6)
在Kodein 3.x
中,有一个名为kodein-conf
的新模块。这允许您创建一个可修改的Kodein实例(只要您在第一次注入完成之前对其进行修改),并且如果需要,它还包含一个共享用的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,以及预定义的全局实例The God Complex: One True Kodein
作为帮助程序,您可以使用新的KodeinGlobalAware
接口在您的类中自然访问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
以在类中执行相同的透明类型注入,同时默认为global
实例。
如果您只想注入Kodein,无论是全局实例还是特定实例,请参阅:Injecting Kodein instances within binding declarations作为替代。