首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Guice + Kotlin绑定对象列表

使用Guice + Kotlin绑定对象列表
EN

Stack Overflow用户
提问于 2016-04-14 13:49:23
回答 3查看 3.4K关注 0票数 9

我正在用Kotlin编写一个JavaFX应用程序,其控制器定义如下:

代码语言:javascript
复制
class MainController {

    @Inject private lateinit var componentDescriptors: List<ComponentDescriptor>
    /* More code goes here */

}

我正在使用Guice进行依赖性管理。我正在尝试注入通过java.util.ServiceLoader加载的类实例列表。我的问题是定义一个绑定,将加载的对象实例列表注入到声明的字段中。我尝试了基于注释的配置:

代码语言:javascript
复制
internal class MyModule: AbstractModule() {

    override fun configure() { }

    @Provides @Singleton
    fun bindComponentDescriptors(): List<ComponentDescriptor> = 
            ServiceLoader.load(ComponentDescriptor::class.java).toList()

}

和多绑定扩展(在corse的字段定义中设置的切换列表):

代码语言:javascript
复制
internal class MyModule: AbstractModule() {

    override fun configure() {
        val componentDescriptorBinder = Multibinder.newSetBinder(binder(), ComponentDescriptor::class.java)
        ServiceLoader.load(ComponentDescriptor::class.java).forEach {
            componentDescriptorBinder.addBinding().toInstance(it)
        }
    }

}

但这两种方法都会导致相同的错误:

代码语言:javascript
复制
No implementation for java.util.List<? extends simpleApp.ComponentDescriptor> was bound.
  while locating java.util.List<? extends simpleApp.ComponentDescriptor>
    for field at simpleApp.MainController.componentDescryptors(MainController.kt:6)
  while locating simpleApp.MainController

1 error
    at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1042)
    at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1001)
    at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
    at com.gluonhq.ignite.guice.GuiceContext.getInstance(GuiceContext.java:46)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:929)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
    ... 12 more

我开始怀疑它在某种程度上与Kotlin遗传变异和Guice严格类型检查有关。但是我不知道如何声明绑定,所以Guice将知道如何注入到这个字段中。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-04-14 14:02:26

是的,它是因为变化而发生的,但是有一个方法可以让它发挥作用。

代码语言:javascript
复制
class MainController {
    @JvmSuppressWildcards
    @Inject
    private lateinit var componentDescriptors: List<ComponentDescriptor>    
}

默认情况下,Kotlin为List<? extends ComponentDescriptor>字段生成componentDescriptors签名。@JvmSuppressWildcards使其生成一个简单的参数化签名List<ComponentDescriptor>

票数 19
EN

Stack Overflow用户

发布于 2016-09-19 15:32:22

@Michael给出了正确的answer和解释。下面是一个为那些喜欢测试模块的人测试Set多绑定的单元策略的示例:

代码语言:javascript
复制
class MyModuleTest {

  @JvmSuppressWildcards
  @Inject
  private lateinit var myTypes: Set<MyType>

  @Before fun before() {
    val injector = Guice.createInjector(MyModule())
    injector.injectMembers(this)
  }

  @Test fun multibindings() {
    assertNotNull(myTypes)
    assertTrue(myTypes.iterator().next() is MyType)
  }
}
票数 3
EN

Stack Overflow用户

发布于 2018-12-10 22:15:23

@Michael注释正在运行。如果要在构造函数中执行注入,则需要执行以下操作

代码语言:javascript
复制
class MainController @Inject consturctor(
    private var componentDescriptors: List<@JvmSuppressWildcards ComponentDescriptor>  
) {}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36625168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档