Kotlin数据类:如果在编译时不知道属性名称,该如何设置属性?

时间:2019-12-19 19:03:45

标签: kotlin

因此,我正在尝试在编译后设置数据类的属性。我正在尝试使用方括号表示法,但是IDE用以下命令对我{之以鼻:No set method providing array access

我做了一些研究,看来我需要使用Reflection api。使用memberProperties进行了尝试,但是在确定属性后,就没有setter方法了。所以,我在这里希望找到一些指导。

这是我想要做的一个人为的例子:

data class EmailMessageStats(
    var bounce: Int = 0,
    var click: Int = 0,
    var deferred: Int = 0,
    var delivered: Int = 0,
    var dropped: Int = 0,
    var open: Int = 0,
    var processed: Int = 0,
    var spamreport: Int = 0
)

val sampleResponseFromDatabase = listOf(
    mapOf("type" to "bounce", "value" to 148),
    mapOf("type" to "click", "value" to 142),
    mapOf("type" to "deferred", "value" to 286),
    mapOf("type" to "delivered", "value" to 700),
    mapOf("type" to "dropped", "value" to 152),
    mapOf("type" to "open", "value" to 550),
    mapOf("type" to "processed", "value" to 1000),
    mapOf("type" to "spamreport", "value" to 140)
)

var summary = EmailMessageStats()
for (row in sampleResponseFromDatabase) {
    val type = row["type"] // e.g. bounce
    val value = row["value"] //e.g. 148
    summary[type] = value
}

println(summary)

2 个答案:

答案 0 :(得分:1)

我为此功能制作了Kotlin扩展功能:

fun Any.setPropertyValue(propName: String, value: Any) {
    for (prop in this::class.declaredMemberProperties) {
        if (prop.name == propName) {
            (prop as? KMutableProperty<*>)?.setter?.call(this, value)
        }
    }
}

类似地获得属性值:

fun Any.getPropertyValue(propName: String): Any? {
    for (prop in this::class.declaredMemberProperties) {
        if (prop.name == propName) return prop.getter.call(this)
    }
    return null
}

在这里,您可以按如下所示设置属性:

var summary = EmailMessageStats()
for (row in sampleResponseFromDatabase) {
    val type = row["type"] // e.g. bounce
    val value = row["value"] //e.g. 148
    summary.setPropertyValue(type, value)
}

如果只希望与declaredMemberProperties相关的字段,请记住使用EmailMessageStats。否则,如果EmailMessageStats是从另一个对象扩展的,它也将迭代该对象的字段。

答案 1 :(得分:0)

我通过以下方式得到了它:

data class Item(var name: String, var description: String?)

运行时

val item = "Runtime item object"
val property = "name"
val value = "Updated value of name"

val jo = JsonParser().parse( Gson().toJson(item) ).asJsonObject

if(jo.has(property)) {
    jo.remove(property)
    jo.addProperty(property, value)
}

val item = Gson().fromJson(jo, Item::class.java)