web-dev-qa-db-fra.com

Classe de données Kotlin: comment lire la valeur d'une propriété si je ne connais pas son nom au moment de la compilation?

Comment puis-je lire la valeur d'une propriété dans une instance de classe de données Kotlin si le nom de la propriété n'est connu qu'au moment de l'exécution?

15
Elifarley

Voici une fonction pour lire une propriété d'une instance d'une classe étant donné le nom de la propriété ( lève une exception si la propriété n'est pas trouvée, mais vous pouvez changer ce comportement ):

import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberProperties

@Suppress("UNCHECKED_CAST")
fun <R> readInstanceProperty(instance: Any, propertyName: String): R {
    val property = instance::class.memberProperties
                     // don't cast here to <Any, R>, it would succeed silently 
                     .first { it.name == propertyName } as KProperty1<Any, *> 
    // force a invalid cast exception if incorrect type here
    return property.get(instance) as R  
}

exemple d'utilisation:

// some data class
data class MyData(val name: String, val age: Int)
val sample = MyData("Fred", 33)

// and reading property "name" from an instance...
val name: String = readInstanceProperty(sample, "name")

// and reading property "age" placing the type on the function call...
val age = readInstanceProperty<Int>(sample, "age")

println(name) // Fred
println(age)  // 33

Remarque: Le org.jetbrains.kotlin:kotlin-reflect une dépendance est requise pour utiliser la réflexion Kotlin.

17
Jayson Minard

Les réponses ci-dessus n'ont pas fonctionné pour moi, j'ai donc créé une fonction d'extension pour cela:

@Throws(IllegalAccessException::class, ClassCastException::class)
inline fun <reified T> Any.getField(fieldName: String): T? {
    this::class.memberProperties.forEach { kCallable ->
        if (fieldName == kCallable.name) {
            return kCallable.getter.call(this) as T?
        }
    }
    return null
}

Ceci est un exemple d'appel:

val valueNeeded: String? = yourObject.getField<String>("exampleFieldName")

Incluez également ceci dans le build.gradle de votre application:

implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
0
Adam Kis