15

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?

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
junk
  • 917
  • 3
  • 11
  • 29
  • 2
    Are you trying to replace the delegate with another instance, or just reflectively set the property value like `record.name = "aa"`? – hotkey Jun 01 '17 at 10:37
  • hey maybe my answer helps: https://stackoverflow.com/a/56115232/2939453 – Adam Kis May 13 '19 at 15:33

1 Answers1

43

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.

hotkey
  • 140,743
  • 39
  • 371
  • 326
  • 1
    Callable expects 2 arguments ? why ? what is the kotlin-reflect version? – junk Jun 01 '17 at 11:24
  • 1
    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. – hotkey Jun 01 '17 at 11:27