Kotlin:我怎样才能获得成员资产的授权类?

问题描述:

如何获取成员属性的委托类?Kotlin:我怎样才能获得成员资产的授权类?

这样,我的意思是有可能完成这样的功能:

inline fun <reified T> delegationExample(t: T) { 
    for (prop in T::class.declaredMemberProperties) { 
     val delegatedClass = // what to do?! 
    } 
} 

凡委托类可能看起来像:

class DelegationExample { 
    operator fun getValue(ref: Any, prop: KProperty<*>) = 0 
} 

的报关类可能是这样的:

object Example { 
    val a by DelegationExample() 
    val b by DelegationExample() 
    val c by DelegationExample() 
} 

要查找委托给委托类与类的实例一起性质,这里是一个效用函数:

data class DelegatedProperty<T : Any, DELEGATE : Any>(val property: KProperty1<T, *>, val delegatingToInstance: DELEGATE) 

inline fun <reified T : Any, DELEGATE : Any> findDelegatingPropertyInstances(instance: T, delegatingTo: KClass<DELEGATE>): List<DelegatedProperty<T, DELEGATE>> { 
    return T::class.declaredMemberProperties.map { prop -> 
     val javaField = prop.javaField 
     if (javaField != null && delegatingTo.java.isAssignableFrom(javaField.type)) { 
      javaField.isAccessible = true // is private, have to open that up 
      @Suppress("UNCHECKED_CAST") 
      val delegateInstance = javaField.get(instance) as DELEGATE 
      DelegatedProperty(prop, delegateInstance) 
     } else { 
      null 
     } 
    }.filterNotNull() 
} 

的几个注意事项:

  • 首先纠正你的具体化键入TT: Any或者您无法访问Kotlin反射中的所有扩展名,包括declaredMemberProperties
  • 从属性参考到现场最容易,以确保你实际上在谈论某个属性,因此每个declaredMemberProperties使用​​来做到这一点。
  • 由于​​是一个自定义getter,可以为空,它被保存到一个局部变量,所以智能铸造将在以后工作。
  • 然后,如果此字段的类型与您正在查找的代理类相同,则可以访问该字段。
  • 但首先你必须强制该字段的可访问性,因为它是一个private字段。

测试程序运行以下命令:

class DelegationExample { 
    operator fun getValue(ref: Any, prop: KProperty<*>) = 0 
} 

class Example { 
    val a by DelegationExample() 
    val b by DelegationExample() 
    val c by DelegationExample() 
} 

fun main(args: Array<String>) { 
    findDelegatingPropertyInstances(Example(), DelegationExample::class).forEach { 
     println("property '${it.property.name}' delegates to instance of [${it.delegatingToInstance}]") 
    } 
} 

的输出是一样的东西:

property 'a' delegates to instance of [[email protected]] 
property 'b' delegates to instance of [[email protected]] 
property 'c' delegates to instance of [[email protected]] 
+0

我的补丁:https://gist.github.com/Jire/df9c99fac5e4d3f35e1a6c517716f989 – Jire

+1

当然,都做类似的事情。我想在这个例子中返回委托的所有东西,并且不会在任何我不需要的地方调用'isAccessible'(在调用它的时候会有影响吗?) –

+0

您引用的补丁(Jire)只会在只是一个声明的属性,它使用作为第二个参数传递的委托。无论如何,当有两个或更多属性使用相同的代理时,为给定属性找到代表?我很想有一个可以做到这一点的功能。我试图弄清楚,但我不认为这是可能的。 –

关于字节代码级委托属性不推迟从常规(publi c getter/setter和一个私人字段)。

你可以去的一种方法是扫描Example的私人字段并过滤那些有operator getValue(thisRef: R, KProperty<*>)的字段。从技术上讲,一个字段可能包含代理对象val x = lazy {1},但这不太可能。