我有一个对象:
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/