¿Cómo uso el object Kotlin por reflexión?

Digamos que necesito establecer la propiedad A dada por una Cadena en el object Kotlin O dada por una Cadena por reflexión. Si O fuera una class, podría hacer algo como esto (sin tener en count que no tiene sentido):

fun setValue(ownerClassName: String, fieldName: String, value : Any) { val enclosingClass = Class.forName(ownerClassName).newInstance() val enclosingClassField = enclosingClass.javaClass.getDeclanetworkingField(fieldName) enclosingClassField.isAccessible = true enclosingClassField.set(enclosingClass, value) } 

¿Pero cómo lo haría si O es un object?

KClass tiene un campo objectInstance :

 Class.forName(ownerClassName).kotlin.objectInstance 

Esto está integrado en la reflexión de Kotlin.

Devuelve : la instancia de la statement del object, o nulo si esta class no es una statement del object.

Esto sería aún mejor si KClass tuviera un método forName , pero lamentablemente no (todavía), así que tenemos que get la Class (Java) y convertirla a KClass .

Puede get una instancia de KClass de una Class utilizando la propiedad de extensión .kotlin .

Luego puedes continuar con el rest de tu código. Convertí esto en la biblioteca de reflexión de Kotlin:

 val kClass = Class.forName(ownerClassName).kotlin val instance = kClass.objectInstance ?: kClass.java.newInstance() // Get the object OR a new instance if it doesn't exist val member = kClass.memberProperties .filterIsInstance<KMutableProperty<*>>() // Has to be a mutable property, otherwise we can't set it .filter { it.name == fieldName } // Check the name .firstOrNull() member?.setter?.call(instance, value) // Set the property 

Aquí hay una testing de trabajo:

 object TestObject { var field = 3 } fun setValue(ownerClassName: String, fieldName: String, value: Any) { val kClass = Class.forName(ownerClassName).kotlin val instance = kClass.objectInstance ?: kClass.java.newInstance() val member = kClass.memberProperties.filterIsInstance<KMutableProperty<*>>() .firstOrNull { it.name == fieldName } member?.setter?.call(instance, value) } fun main(args: Array<String>) { println(TestObject.field) // 3 setValue("some.package.TestObject", "field", 4) println(TestObject.field) // 4 } 

object se traduce a una class con un constructor privado y un campo estático llamado INSTANCE donde la única instancia se almacena cuando se carga esta class, por lo que reemplaza Class.forName(ownerClassName).newInstance() con

 Class.forName(ownerClassName).getDeclanetworkingField("INSTANCE").get(null) 

Deberia trabajar.


Javadoc:

  • Class#forName
  • Class#getDeclanetworkingField
  • Field#get
  • ¿Cómo get un KType en Kotlin?
  • ¿Cómo puedo crear una instancia de un object usando valores de parameters de constructor pnetworkingeterminados en Kotlin?
  • Kotlin, cómo recuperar el valor del campo a través de la reflexión
  • ¿Cómo hacer inferencia tipo Kotlin desde la reflexión KClass?
  • Kotlin: ¿Cómo se accede a los methods get y setValue de un delegado?
  • ¿Cómo get una KClass de Array?
  • Kotlin: isAssignableFrom y reflexiones del tipo de reflexión
  • ¿Puedo usar kotlin.reflect para get un valor de un campo
  • ¿Hay alguna manera de identificar una class de datos Kotlin de una class regular de Kotlin?
  • ¿Es seguro llamar a kclass.memberProperties en un object desconocido (Cualquiera)?
  • ¿Cómo puedo establecer una propiedad de un object complementario en Kotlin a través de la reflexión?