【问题标题】:Read Kotlin function annotation value using reflection?使用反射读取 Kotlin 函数注释值?
【发布时间】:2017-11-27 12:04:41
【问题描述】:

给定这样的接口方法(Android Retrofit),我如何在运行时从 Kotlin 代码中读取注解参数中指定的 URL 路径?

ApiDefinition 接口:

@GET("/api/somepath/objects/")
fun getObjects(...)

读取注解值:

val method = ApiDefinition::getObjects.javaMethod
val verb = method!!.annotations[0].annotationClass.simpleName ?: ""
// verb contains "GET" as expected
// But how to get the path specified in the annotation?
val path = method!!.annotations[0].????????

更新 1

感谢您的回答。我仍然在苦苦挣扎,因为我看不到使用什么类型来执行以下操作:

val apiMethod = ApiDefinition::getObjects

....然后将该函数引用传递给这样的方法(它被重用)

private fun getHttpPathFromAnnotation(method: Method?) : String {
    val a = method!!.annotations[0].message
}

IntelliJ IDE 建议我使用 KFunction5 作为函数参数类型(据我所知,它不存在)并且似乎还需要我指定该方法的所有参数类型,这使得通用调用获取注释属性是不可能的。没有 Kotlin 等效的“方法”吗?一种可以接受任何方法的类型?我尝试了 KFunction,但没有成功。

更新 2

感谢您澄清事情。我已经到了这一点:

ApiDefinition(改造接口)

@GET(API_ENDPOINT_LOCATIONS)
fun getLocations(@Header(API_HEADER_TIMESTAMP) timestamp: String,
                 @Header(API_HEADER_SIGNATURE) encryptedSignature: String,
                 @Header(API_HEADER_TOKEN) token: String,
                 @Header(API_HEADER_USERNAME) username: String
                 ): Call<List<Location>>

获取注解参数的方法:

private fun <T> getHttpPathFromAnnotation(method: KFunction<T>) : String {
    return method.annotations.filterIsInstance<GET>().get(0).value
}

调用以获取特定方法的路径参数:

    val path = getHttpPathFromAnnotation<ApiDefinition>(ApiDefinition::getLocations as KFunction<ApiDefinition>)

隐式转换似乎是必要的,或者类型参数需要我提供一个 KFunction5 类型。

此代码有效,但它具有硬编码的 GET 注释,有没有办法使它更通用?我怀疑我可能需要查找 GET、POST 和 PUT 并返回第一个匹配项。

【问题讨论】:

  • KFunction 应该可以工作。 private fun &lt;T&gt; getHttpPathFromAnnotation(method: KFunction&lt;T&gt;?)

标签: android kotlin retrofit2 kotlin-reflect


【解决方案1】:

直接使用 Kotlin KFunction 而不是 javaMethod(无论如何你都在使用 Kotlin!),findAnnotation 用于简洁、惯用的代码。

如果注释碰巧不是第一个注释,这也将起作用,annotations[0] 可能会中断。

val method = ApiDefinition::getObjects

val annotation = method.findAnnotation<GET>() // Will be null if it doesn't exist

val path = annotation?.path

基本上所有findAnnotation 所做的都是返回

annotations.filterIsInstance<T>().firstOrNull()

【讨论】:

    猜你喜欢
    • 2014-02-12
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多