要查找委託給委託類與類的實例一起性質,這裏是一個效用函數:
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]]
我的補丁:https://gist.github.com/Jire/df9c99fac5e4d3f35e1a6c517716f989 – Jire
當然,都做類似的事情。我想在這個例子中返回委託的所有東西,並且不會在任何我不需要的地方調用'isAccessible'(在調用它的時候會有影響嗎?) –
您引用的補丁(Jire)只會在只是一個聲明的屬性,它使用作爲第二個參數傳遞的委託。無論如何,當有兩個或更多屬性使用相同的代理時,爲給定屬性找到代表?我很想有一個可以做到這一點的功能。我試圖弄清楚,但我不認爲這是可能的。 –