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 ?

Solutions Collecting From Web of "Acceda al tipo de delegado de Kotlin sin una instancia"

¿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.