通用指南模块
Generic Guice Module
是否可以定义一个通用的 Guice 模块?
我总是得到 CreationException
:
Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:
1) com.example.test.GenericClass<T> cannot be used as a key; It is not fully specified.
1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:470)
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
at com.google.inject.Guice.createInjector(Guice.java:99)
at com.google.inject.Guice.createInjector(Guice.java:73)
at com.google.inject.Guice.createInjector(Guice.java:62)
at com.example.test.GenericModuleKt.main(genericModule.kt:23)
at com.example.test.GenericModuleKt.main(genericModule.kt)
这是我的示例代码:
package com.example.test
import com.google.inject.AbstractModule
import com.google.inject.Guice
import com.google.inject.Key
import com.google.inject.TypeLiteral
class SomeClass
class GenericClass<T>
class GenericModule<T> : AbstractModule() {
override fun configure() {
bind(object : TypeLiteral<GenericClass<T>>(){})
}
}
fun main() {
val injector = Guice.createInjector(
GenericModule<SomeClass>()
)
val instance : GenericClass<SomeClass> =
injector.getInstance(object : Key<GenericClass<SomeClass>>(){})
}
编辑:在 Yurii Melnychuk 的帮助下工作示例
您需要使用Types.newParameterizedType
来指定泛型class:
class SomeClass
class GenericClass<T>
class GenericModule(
private val genericClass: Class<*>
) : AbstractModule() {
override fun configure() {
val paraType = Types.newParameterizedType(GenericClass::class.java, genericClass)
bind(TypeLiteral.get(paraType))
}
}
fun main() {
val injector = Guice.createInjector(
GenericModule(SomeClass::class.java)
)
val instance : GenericClass<SomeClass> =
injector.getInstance(object : Key<GenericClass<SomeClass>>(){})
}
如果遇到任何问题(尤其是在使用通用接口时),请尝试使用 Java 而不是 Kotlin。这为我解决了一些问题。
通用类型信息在运行时被删除,所以不可能按照你想要的方式做(至少在 Java,Kotlin 在这方面可能有所不同,但我不熟悉它,也许具体化的仿制药可以提供帮助)。
但从 Java 的角度来看,我宁愿将 TypeLiteral
/Type
作为构造函数参数传递给模块并绑定它(com.google.inject.util.Types#newParameterizedType
应该有帮助)。
是否可以定义一个通用的 Guice 模块?
我总是得到 CreationException
:
Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:
1) com.example.test.GenericClass<T> cannot be used as a key; It is not fully specified.
1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:470)
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
at com.google.inject.Guice.createInjector(Guice.java:99)
at com.google.inject.Guice.createInjector(Guice.java:73)
at com.google.inject.Guice.createInjector(Guice.java:62)
at com.example.test.GenericModuleKt.main(genericModule.kt:23)
at com.example.test.GenericModuleKt.main(genericModule.kt)
这是我的示例代码:
package com.example.test
import com.google.inject.AbstractModule
import com.google.inject.Guice
import com.google.inject.Key
import com.google.inject.TypeLiteral
class SomeClass
class GenericClass<T>
class GenericModule<T> : AbstractModule() {
override fun configure() {
bind(object : TypeLiteral<GenericClass<T>>(){})
}
}
fun main() {
val injector = Guice.createInjector(
GenericModule<SomeClass>()
)
val instance : GenericClass<SomeClass> =
injector.getInstance(object : Key<GenericClass<SomeClass>>(){})
}
编辑:在 Yurii Melnychuk 的帮助下工作示例
您需要使用Types.newParameterizedType
来指定泛型class:
class SomeClass
class GenericClass<T>
class GenericModule(
private val genericClass: Class<*>
) : AbstractModule() {
override fun configure() {
val paraType = Types.newParameterizedType(GenericClass::class.java, genericClass)
bind(TypeLiteral.get(paraType))
}
}
fun main() {
val injector = Guice.createInjector(
GenericModule(SomeClass::class.java)
)
val instance : GenericClass<SomeClass> =
injector.getInstance(object : Key<GenericClass<SomeClass>>(){})
}
如果遇到任何问题(尤其是在使用通用接口时),请尝试使用 Java 而不是 Kotlin。这为我解决了一些问题。
通用类型信息在运行时被删除,所以不可能按照你想要的方式做(至少在 Java,Kotlin 在这方面可能有所不同,但我不熟悉它,也许具体化的仿制药可以提供帮助)。
但从 Java 的角度来看,我宁愿将 TypeLiteral
/Type
作为构造函数参数传递给模块并绑定它(com.google.inject.util.Types#newParameterizedType
应该有帮助)。