Не удалось получить значение из аннотации - PullRequest
0 голосов
/ 27 февраля 2019

Это определение аннотации:

@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 голосов
/ 27 февраля 2019

Насколько я понимаю, вы просто хотите увидеть значение аннотации для данного свойства.

Сначала давайте объявим аннотацию.

@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)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...