从注释获取价值失败

时间:2019-02-27 01:53:10

标签: kotlin annotations

这是注释定义:

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class MyAnno(val desc: String, val comment: String) { }

下面是MyAnno使用的地方:

class MyAnnoUser {
    @MyAnno(desc = "name", comment = "name comment")
    lateinit var name: String

    @MyAnno(desc = "age", comment = "age comment")
    var age: Int = 0

    @MyAnno(desc =  "money", comment = "money comment")
    var money: Double = 0.0

    @MyAnno(desc =  "gender", comment = "gender comment")
    var gender: Boolean = false

    override fun toString(): String {
        return "(name: $name; age: $age; money: $money; gender: ${if (gender) "men" else "women"})"
    }
}

这里是读取MyAnno中值的代码:

class MyAnnoExpression(val obj: Any, val context: Context) {

    val numTypeSet = setOf("Int", "Double", "Byte")

    fun expression() {

        val clazz = obj::class

        clazz.declaredMemberProperties.forEach { prop ->
            val mutableProp = try {
                prop as KMutableProperty<*>
            } catch (e: Exception) {
                null
            } ?: return@forEach

            val desc = mutableProp.findAnnotation<MyAnno>()
            desc?.let {
                val propClassName = mutableProp.returnType.toString().removePrefix("kotlin.")
                when (propClassName) {
                    in numTypeSet -> mutableProp.setter.call(obj, (readProp(it, context) as kotlin.String).toNum(propClassName))
                    "String" -> mutableProp.setter.call(obj, (readProp(it, context) as kotlin.String))
                    "Boolean" -> mutableProp.setter.call(obj, (readProp(it, context) as kotlin.String).toBoolean())
                }
            }
        }
    }

    private fun readProp(value: MyAnno, context: Context): Any? {
        val prop = Properties()
        val input = context.assets.open("app.properties")
        prop.load(InputStreamReader(input, "utf-8"))
        return prop.get(value.desc)
    }
}

现在,调试器向我显示了value函数中readProp(...)的以下信息:

@com.demo.basekotlin.MyAnno(comment=age comment, desc=age)

但是从desc读取value时出现异常:

An exception occurs during Evaluate Expression Action : org.jetbrains.eval4j.VOID_VALUE cannot be cast to org.jetbrains.eval4j.AbstractValue

我在代码中找不到任何错误,是否需要其他程序设置?

1 个答案:

答案 0 :(得分:0)

据我了解,您只想查看给定属性的注释值。

首先,让我们声明一个注释。

@Target(PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
annotation class PropertyAnnotation(val desc: String)

容器:

class Container {

    @PropertyAnnotation("Name")
    var name: String? = null

    @PropertyAnnotation("Age")
    var age: Int = -1

    var notAnnotatedProperty: String = "not annotated"
}

最后,负责获取所有声明的属性的代码,然后找到标注为PropertyAnnotation的属性,将其强制转换为它,并从中获取价值。

fun main() {

    val container = Container()

    container::class.declaredMemberProperties.forEach { property ->
        (property.annotations.find {
            it is PropertyAnnotation
        } as? PropertyAnnotation)?.let {
            println("Property: `$property` is ${it.desc}")
        }
    }

}

输出:

Property: `var Container.age: kotlin.Int` is Age
Property: `var Container.name: kotlin.String?` is Name

丑陋。但是,让我们使用更多的Kotlin pro-dev功能。

让我们为任何非空类型创建扩展函数,该函数返回给定类型的所有成员属性:

inline fun <reified T : Any> Any.getMemberProperty(): List<T> {
    return this::class.declaredMemberProperties.mapNotNull { prop ->
        (prop.annotations.find { ann -> ann is T }) as? T
    }
}

现在的用法:

fun main() {

    val container = Container()

    container.getMemberProperty<PropertyAnnotation>().forEach {
        println(it.desc)
    }
}