在没有实例的情况下访问Kotlin代理类型

时间:2017-10-22 03:41:12

标签: reflection properties delegates kotlin

我已阅读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

1 个答案:

答案 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")
}

您将获得delegatedProperty2customDelegate。如果您只想获得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