如何从Kodein中获取指定父类型的已绑定单例实例?
解决方案:从Kodein中筛选指定类型的实例
你的核心需求是从已绑定A、B、C(均实现SharedInterface)和D的Kodein实例中,获取前三者的实例并排除D,下面提供两种更优雅的解决思路:
方案一:优化集合绑定写法(推荐)
你之前的集合绑定写法出错是因为inSet()的使用方式不对——它是用来向已定义的集合绑定中添加元素,而非直接绑定子类并加入集合。我们可以用also块简化代码,避免重复绑定:
interface SharedInterface {} class A : SharedInterface class B : SharedInterface class C : SharedInterface class D fun main(args: Array<String>) { val kodein = Kodein { // 先定义SharedInterface的集合绑定 bind<Set<SharedInterface>>() from setBinding() // 绑定A的单例,同时将其加入集合 bind<A>() with singleton { A() } also { bind<SharedInterface>().inSet() with instanceBinding() } // 同理处理B和C bind<B>() with singleton { B() } also { bind<SharedInterface>().inSet() with instanceBinding() } bind<C>() with singleton { C() } also { bind<SharedInterface>().inSet() with instanceBinding() } // 单独绑定D,不加入集合 bind<D>() with singleton { D() } } // 直接获取集合,里面就是A、B、C的实例 val sharedInstances = kodein.instance<Set<SharedInterface>>() }
这种写法既保留了A、B、C各自的独立绑定,又自动将它们加入到SharedInterface集合中,比你最后一种繁琐的写法简洁很多,也符合Kodein的设计规范。
方案二:从已有Kodein实例中筛选(无需修改绑定代码)
如果不想改动原有的绑定逻辑,也可以通过遍历Kodein容器的绑定信息,筛选出实现SharedInterface的类型并获取实例:
fun main(args: Array<String>) { val kodein = Kodein { bind<A>() with singleton { A() } bind<B>() with singleton { B() } bind<C>() with singleton { C() } bind<D>() with singleton { D() } } val sharedInstances = kodein.container.bindings .keys // 筛选出类型为SharedInterface子类的绑定 .filter { key -> val boundType = key.type.jvmErasure SharedInterface::class.java.isAssignableFrom(boundType.java) } // 获取对应实例并转为SharedInterface类型 .map { key -> kodein.instance(key.type) as SharedInterface } }
⚠️ 注意:这种方式依赖Kodein的内部API(container.bindings),未来版本可能会有变化,所以如果是长期维护的项目,更推荐方案一。
分析你之前的错误
你尝试的bind<A>().inSet() with singleton { A() }会抛出异常,是因为inSet()需要配合父类型的集合绑定使用——它的作用是向Set<SharedInterface>中添加元素,而不是绑定A自身。正确的集合元素绑定应该是针对父类型的,而非子类。
内容的提问来源于stack exchange,提问作者atok
相关产品推荐
相关产品推荐

