2016-04-14 18 views
5

Tôi đang viết một ứng dụng JavaFX trong Kotlin với định nghĩa điều khiển sau:danh sách Bind của các đối tượng sử dụng Guice + Kotlin

class MainController { 

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

} 

Tôi đang sử dụng Guice cho quản lý phụ thuộc. Và tôi đang cố gắng để tiêm danh sách các trường hợp lớp được nạp thông qua java.util.ServiceLoader. Vấn đề của tôi là xác định một ràng buộc sẽ đưa vào danh sách các đối tượng được nạp vào trường đã khai báo. Tôi cố gắng cung chú thích dựa trên:

internal class MyModule: AbstractModule() { 

    override fun configure() { } 

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

} 

và multibinding mở rộng (chuyển List để Đặt trong định nghĩa lĩnh vực Corse):

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) 
     } 
    } 

} 

nhưng cả hai cách tiếp cận dẫn đến các lỗi tương tự:

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 

Tôi bắt đầu nghi ngờ rằng bằng cách nào đó nó liên quan đến phương sai gerenic Kotlin và kiểm tra loại nghiêm ngặt Guice. Nhưng tôi không biết làm thế nào để tuyên bố ràng buộc để Guice sẽ biết những gì để tiêm vào lĩnh vực này.

Trả lời

13

Có, điều đó xảy ra do phương sai nhưng có cách để làm cho nó hoạt động.

class MainController { 
    @JvmSuppressWildcards 
    @Inject 
    private lateinit var componentDescriptors: List<ComponentDescriptor>  
} 

Theo mặc định, Kotlin tạo chữ ký cho trường componentDescriptors. Các @JvmSuppressWildcards làm cho nó tạo ra một chữ ký tham số đơn giản List<ComponentDescriptor>.

3

@Michael đưa ra chính xác answer và giải thích. Dưới đây là ví dụ về một chiến lược cho thử nghiệm đơn vị một sự ghép đôi Set cho những người muốn thử nghiệm mô-đun của họ:

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) 
    } 
} 
Các vấn đề liên quan