我已阅读Access property delegate in Kotlin,其中涉及从实例访问委托。从Kotlin 1.1开始,可以使用KProperty::getDelegate
,但是这将返回委托的实例,因此首先需要该类的实例。
现在我想获得代理的类型,而不需要类的实例。考虑一个自定义委托类型CustomDelegate
的库,它希望获得委托给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")
}
如果我有KClass<Example>
但不是Example
的实例,我怎样才能将所有属性委托给CustomDelegate
?
答案 0 :(得分:2)
我可以,因为我有KClass&lt; Example&gt;,但不是。的实例 例如,获取委托给CustomDelegate的所有属性?
您可以根据自己的需要以两种方式进行。
首先,您必须在build.gradle
文件中包含 kotlin-reflect 依赖项:
compile "org.jetbrains.kotlin:kotlin-reflect:1.1.51"
在我看来,如果可以,你应该使用第一种解决方案,因为它是最清晰和最优化的解决方案。相反,第二种解决方案可以处理第一种解决方案无法解决的一种情况。
<强>第一强>
您可以循环声明的属性并检查属性的类型或委托的类型是否为CustomDelegate
。
// Loop on the properties of this class.
Example::class.declaredMemberProperties.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
}
此解决方案只有一个问题,您还会获得类型为CustomDelegate
的字段,因此,在此示例中:
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")
}
您将获得delegatedProperty2
和customDelegate
。如果您只想获得delegatedProperty2
,我发现了一个可怕的解决方案,如果您需要管理此案例,可以使用。
<强>第二强>
如果您检查KPropertyImpl
的源代码,您可以看到如何实施委派。所以,你可以这样做:
// Loop on the properties of this class.
Example::class.declaredMemberProperties.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.declaredFunctions.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
}
在这种情况下,结果只会得到delegatedProperty2
。