How to set delegated property value by reflection in kotlin?
Asked Answered
C

1

17

My entity class:

class User : ActiveRecord<User>() {
    var name by Column(String.javaClass);
    var id by Column(Int.javaClass);
}

now I want to set name value by refelection:

var clazz = User().javaClass
var record = clazz.newInstance()
var field = record.getDeclaredField(it + "$" + "delegate")

field.set(record, "aa")

then error:

entity.Column field ActiveRecord4k.User.name$delegate to java.lang.String

how to do this?

Calvo answered 1/6, 2017 at 10:1 Comment(2)
Are you trying to replace the delegate with another instance, or just reflectively set the property value like record.name = "aa"?Tinsel
hey maybe my answer helps: https://mcmap.net/q/345125/-kotlin-data-class-how-to-read-the-value-of-property-if-i-don-39-t-know-its-name-at-compile-timeMozza
T
44

If you want to reflectively set the property as if it was record.name = "...", then you can use kotlin-reflect, the Kotlin reflection API (see the reference).

With kotlin-reflect, setting a property value is done like this:

val property = outputs::class.memberProperties.find { it.name == "name" }
if (property is KMutableProperty<*>) {
    property.setter.call(record, "value")
}

If the property is delegated, the call will be dispatched to the delegate.

Or, you can do that with Java reflection, finding the setter for your property first:

var setter = clazz.getDeclaredMethod("set" + it.capitalize())
setter.invoke(record, "aa")

But there is no way, at least at this point, to overwrite the delegate instance of that property, because the field storing it, name$delegate, is final.

Tinsel answered 1/6, 2017 at 10:51 Comment(2)
Callable expects 2 arguments ? why ? what is the kotlin-reflect version?Calvo
Oh, it was a mistake in the code, you should actually pass the object and the property value: property.setter.call(record, "value"). Fixed this.Tinsel

© 2022 - 2024 — McMap. All rights reserved.