Acceda al tipo de delegado de Kotlin sin una instancia

He leído el delegado de la propiedad de Access en Kotlin, que trata de acceder a un delegado de una instancia. Uno puede usar KProperty::getDelegate desde Kotlin 1.1, sin embargo, esto devolverá la instancia del delegado y, por lo tanto, necesita primero una instancia de la class.

Ahora quiero get el tipo de delegado sin tener una instancia de la class. Considere una biblioteca con un delegado personalizado tipo CustomDelegate que desee get todas las properties de una class que se delegan en una instancia de CustomDelegate :

 class Example { var nonDelegatedProperty = "I don't care about this property" var delegatedProperty1 by lazy { "I don't care about this too" } var delegatedProperty2 by CustomDelegate("I care about this one") } 

¿Cómo puedo, dado que tengo KClass<Example> , pero no una instancia de Example , get todas las properties delegadas en CustomDelegate ?

¿Cómo puedo, dado que tengo KClass <Ejemplo>, pero no una instancia de Ejemplo, get todas las properties delegadas en CustomDelegate?

Puedes hacerlo de dos maneras dependiendo de tus necesidades.

En primer lugar, debe include la dependencia de kotlin-reflect en su file build.gradle :

 compile "org.jetbrains.kotlin:kotlin-reflect:1.1.51" 

En mi opinión, debe usar la primera solución si puede, porque es la más clara y optimizada. La segunda solución, en cambio, puede manejar un caso que la primera solución no puede.

primero

Puede recorrer las properties declaradas y verificar si el tipo de propiedad o el tipo de delegado es CustomDelegate .

 // Loop on the properties of this class. Example::class.declanetworkingMemberProperties.filter { property -> // If the type of field is CustomDelegate or the delegate is an instance of CustomDelegate, // it will return true. CustomDelegate::class.java == property.javaField?.type } 

Solo hay un problema con esta solución, también obtendrá los campos con el tipo CustomDelegate , así que, dado este ejemplo:

 class Example { var nonDelegatedProperty = "I don't care about this property" val delegatedProperty1 by lazy { "I don't care about this too" } val delegatedProperty2 by CustomDelegate("I care about this one") val customDelegate = CustomDelegate("jdo") } 

Obtendrá customDelegate y customDelegate . Si desea get solo delegatedProperty2 , encontré una solución horrible que puede usar si necesita administrar este caso.

Segundo

Si comtesting el código fuente de KPropertyImpl , puede ver cómo se implementa una delegación. Entonces, puedes hacer algo como esto:

 // Loop on the properties of this class. Example::class.declanetworkingMemberProperties.filter { property -> // You must check in all superclasses till you find the right method. property::class.allSuperclasses.find { val computeField = try { // Find the protected method "computeDelegateField". it.declanetworkingFunctions.find { it.name == "computeDelegateField" } ?: return@find false } catch (t: Throwable) { // Catch KotlinReflectionInternalError. return@find false } // Get the delegate or null if the delegate is not present. val delegateField = computeField.call(property) as? Field // If the delegate was null or the type is different from CustomDelegate, it will return false. CustomDelegate::class.java == delegateField?.type } != null } 

En este caso, obtendrá solo delegatedProperty2 como resultado.

  • Kotlin obtiene la anotación de campo siempre vacía
  • El operador de Kotlin Reflection obtiene la implementación
  • ¿Cómo puedo get una reference a Kotlin KClass por nombre cuando no se ejecuta en la JVM?
  • Obtén la function por nombre dinámicamente en Kotlin
  • Kotlin, cómo recuperar el valor del campo a través de la reflexión
  • ¿Cómo puedo crear una instancia de un object usando valores de parameters de constructor pnetworkingeterminados en Kotlin?
  • Kotlin: ¿Cómo puedo usar la reflexión en los packages?
  • Kotlin comtesting si la function requiere parámetro de instancia