You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:47:02