Я пытаюсь создать универсальный класс для обработки инъекций конфигурации в 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)
...
}
}
Единственная проблема в том, что он работает только в Котлине, потому что inline
не совместим с java. Итак, как мне обойти это?
В качестве бонуса я хотел бы избавиться от явного объявления типа, чтобы val config: ServiceConfig = this.getResource()
могло быть просто val config = this.getResource()
.
return jacksonObjectMapper().readValue(resourceContent) as T
. - person Roland   schedule 14.08.2018Cannot use 'T' as reified type parameter. Use a class instead.
, если использую Kotlin'izedjacksonObjectMapper()
. Если вместо этого я попробуюObjectMapper().readValue(resource, object : TypeReference<T>() {}) as T
, я получу исключение времени выполнения:java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to dk.whatever...
- person beruic   schedule 14.08.2018TypeReference<T>() {}
... по крайней мере, я так думал... если вы просто передаете сам тип (например,dk.whatever.....class
) , тогда это работает? - person Roland   schedule 14.08.2018ClassCastException
- person beruic   schedule 14.08.2018Map<String, String>
. - person beruic   schedule 14.08.2018