kotlin - 使用反射在Kotlin中按字符串设置属性?

标签 kotlin reflection kotlin-reflect

我有一个对象:

class User {
  var id: String? = null
  var name: String? = null
}

和对列表:
val fieldsToChange = listOf<Pair<String, String>>(Pair("name", "foo"), Pair("id", "bar"))

我想迭代成对的低谷列表,并使用反射为给定的属性设置适当的值。

最佳答案

给定类实例obj,我们可以使用obj::class.memberProperties提取具有名称的属性。

我们可以构造从属性名称到属性的映射:

val nameToProperty = obj::class.memberProperties.associateBy(KProperty<*>::name)

然后,我们可以遍历fieldsToChange并检索属性并进行设置:
fieldsToChange.forEach { (propertyName, propertyValue) ->
   nameToProperty[propertyName]
       .takeIf { it is KMutableProperty<*> } // take only "settable" (var) properties
       ?.let { it as KMutableProperty<*> } // cast it to mutable property so we can access setter
       ?.let { it.setter.call(obj, propertyValue) } // call the setter
}

另外,我们可以使这个通用:
fun setFields(obj: Any, fieldsToChange: List<Pair<String, Any?>>) {
    val nameToProperty = obj::class.memberProperties.associateBy(KProperty<*>::name)
    fieldsToChange.forEach { (propertyName, propertyValue) ->
        nameToProperty[propertyName]
                .takeIf { it is KMutableProperty<*> }
                ?.let { it as KMutableProperty<*> }
                ?.let { it.setter.call(obj, propertyValue) }
    }
}

val user = User()
setFields(user, fieldsToChange)

assert(user.name == "foo")
assert(user.id == "bar")

可能的改进是优化nameToProperty以仅包含已经转换为KMutableProperty的MutableProperty

关于kotlin - 使用反射在Kotlin中按字符串设置属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57090841/

相关文章:

kotlin - 绑定(bind)类引用返回协变类型的目的是什么?

kotlin - 以允许可为空类型和使用该类型参数声明 `KClass<T>` 的方式声明函数泛型类型参数

android - 无法使用 Kotlin Jetpack Compose 从一开始就在 Android Studio 中运行任何应用程序

android - 如何修复 android 架构组件分页 onItemAtEndLoaded 进入循环?

google-app-engine - 使用反射将数据从序列化动态转换回 Go 结构

java - 为什么 getClass().getName() 对未打开的模块类起作用?

android - 什么时候需要 kotlin Reflect lib?

android - 从 Android 中的挂起函数并行调用 Kotlin 协程

xml - 解析XML并根据元素值检查值

java - 为什么依赖 ObjectStreamClass.getSerialVersionUID 不安全?