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()
}
的几个注意事项:
- 首先纠正你的具体化键入
T
到T: 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]]
答
关于字节代码级委托属性不推迟从常规(publi c getter/setter和一个私人字段)。
你可以去的一种方法是扫描Example
的私人字段并过滤那些有operator getValue(thisRef: R, KProperty<*>)
的字段。从技术上讲,一个字段可能包含代理对象val x = lazy {1}
,但这不太可能。
我的补丁:https://gist.github.com/Jire/df9c99fac5e4d3f35e1a6c517716f989 – Jire
当然,都做类似的事情。我想在这个例子中返回委托的所有东西,并且不会在任何我不需要的地方调用'isAccessible'(在调用它的时候会有影响吗?) –
您引用的补丁(Jire)只会在只是一个声明的属性,它使用作为第二个参数传递的委托。无论如何,当有两个或更多属性使用相同的代理时,为给定属性找到代表?我很想有一个可以做到这一点的功能。我试图弄清楚,但我不认为这是可能的。 –