java - 避免与 Kotlin 泛型内联
问题描述
我正在尝试构建一个通用类来处理 Kotlin 和 Java 中的配置注入。
基本上,我希望一个类绑定到一个数据类和一个资源文件的路径,该文件应该包含数据类实例的易于写入的反序列化。
到目前为止,我想出的是:
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
class ResourceLoader()
inline fun <reified T : Any> loadObject(resourcePath: String): T {
// Load resource file
val resource = ResourceLoader::class.java.classLoader.getResource(resourcePath)
val resourceContent = resource.readText()
// Return deserialized object
return jacksonObjectMapper().readValue(resourceContent)
}
abstract class ResourceBound<T : Any>(val resourcePath: String) {
inline fun <reified U : T> getResource(): U {
return loadObject(this.resourcePath)
}
}
有了这个,我可以将一个测试类绑定到一个资源文件的存在,如果文件缺少格式错误,它会在光荣的异常中失败,如下所示:
data class ServiceConfig(val endpoint: String, val apiKey: String)
class TestClassLoadingConfig() : ResourceBound<ServiceConfig>("TestConfig.json") {
@Test
fun testThis() {
val config: ServiceConfig = this.getResource()
val client = ServiceClient(config.endpoint, config.apiKey)
...
}
}
唯一的问题是它只适用于 Kotlin,因为inline
它与 java 不兼容。那么我该如何解决呢?
作为奖励,我想摆脱显式类型声明,所以val config: ServiceConfig = this.getResource()
可以是val config = this.getResource()
.
解决方案
我最近偶然发现了同样的问题,并通过传递 aTypeReference
作为第二个参数来解决它。
我的基本配置类:
package config
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.kotlin.KotlinModule
open class BaseConfig<T>(configFile: String, typeReference: TypeReference<T>) {
val config: T
init {
val mapper = ObjectMapper(YAMLFactory())
mapper.registerModule(KotlinModule())
val inputStream = this.javaClass.classLoader
.getResourceAsStream(configFile)
config = mapper.readValue(inputStream, typeReference)
}
}
示例数据类:
package config.dto
data class MessageDto(
val `example messages`: List<String>
)
示例对象:
package config
import com.fasterxml.jackson.core.type.TypeReference
import config.dto.MessageDto
object Message: BaseConfig<MessageDto>("messages.yml", object: TypeReference<MessageDto>() {}) {
val exampleMessages: List<String> = config.`example messages`
}
示例 yaml:
example messages:
- "An example message"
- "Another example message"
它并不像我希望的那样简洁,但它确实有效,它为我提供了一种将配置文件中的内容映射到任何数据类的灵活方式。
推荐阅读
- activerecord - 如何在 hasMany 关系中添加很少的条件?
- javascript - 如果 .next 与当前元素之后的另一个元素不匹配,则插入文本
- java - 如何返回点之间和括号之前的字符串
- bash - 使用 bash shell 从 json 字符串中的文件夹映射文件名
- android - iOS/Android - 通过 SDK 禁用移动数据(蜂窝数据)
- c# - EF Core - 等效于 IQueryable 搜索的表达式树
- c# - EF 6 保存多级子实体和多个父级
- rest - REST org.xml.sax.SAXParseException;行号:1;列号:1;文件过早结束
- python - 最佳解决方案的建议 - Python
- javascript - 使用 Jest 测试 Redux 和 Axios 获取中间件