2016-04-14 22 views
5

मैं निम्नलिखित नियंत्रक परिभाषा के साथ Kotlin में एक JavaFX आवेदन लिख रहा हूँ का उपयोग कर वस्तुओं की बाइंड सूची:Guice + Kotlin

class MainController { 

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

} 

मैं निर्भरता प्रबंधन के लिए Guice उपयोग कर रहा हूँ। और मैं java.util.ServiceLoader के माध्यम से लोड कक्षा के उदाहरणों की सूची इंजेक्ट करने की कोशिश कर रहा हूं। मेरी समस्या एक बाध्यकारी परिभाषित करना है जो घोषित क्षेत्र में लोड ऑब्जेक्ट उदाहरणों की सूची को इंजेक्ट करेगा। मैंने कोशिश की एनोटेशन आधारित प्रावधान:

internal class MyModule: AbstractModule() { 

    override fun configure() { } 

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

} 

और multibinding विस्तार (सूची स्विच कोर्स के क्षेत्र परिभाषा सेट करने के लिए):

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

} 

लेकिन इन तरीकों के दोनों एक ही गलती की ओर जाता है:

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 

मुझे संदेह है कि यह किसी भी तरह से कोटलिन भूगर्भीय भिन्नता और गुइस सख्त प्रकार की जांच से संबंधित है। लेकिन मुझे नहीं पता कि बाध्यकारी घोषित कैसे करें ताकि गुइस को पता चलेगा कि इस क्षेत्र में क्या इंजेक्ट करना है।

उत्तर

13

हां, यह भिन्नता के कारण होता है लेकिन इसे काम करने का एक तरीका है।

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

डिफ़ॉल्ट Kotlin तक componentDescriptors क्षेत्र के लिए List<? extends ComponentDescriptor> हस्ताक्षर उत्पन्न करता है। @JvmSuppressWildcards यह एक साधारण पैरामीटरयुक्त हस्ताक्षर List<ComponentDescriptor> उत्पन्न करता है।

3

@ माइकल सही answer और स्पष्टीकरण देता है। यहां यूनिट परीक्षण के लिए एक रणनीति का उदाहरण दिया गया है जो उनके मॉड्यूल का परीक्षण करना पसंद करते हैं Set मल्टीबाइंडिंग:

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