简体   繁体   English

在没有实例的情况下访问 Kotlin 委托类型

[英]Access Kotlin Delegate Type without an Instance

I have read Access property delegate in Kotlin which is about accessing a delegate from an instance.我已经阅读了 Kotlin 中的 Access 属性委托,它是关于从实例访问委托的。 One can use KProperty::getDelegate since Kotlin 1.1, however this will return the instance of the delegate and therefore needs an instance of the class first.从 Kotlin 1.1 开始可以使用KProperty::getDelegate ,但是这将返回委托的实例,因此首先需要一个类的实例。

Now I want to get the type of the delegate without having an instance of the class.现在我想在没有类的实例的情况下获取委托的类型。 Consider a library with a custom delegate type CustomDelegate that want's to get all properties of a class that are delegated to an instance of CustomDelegate :考虑一个具有自定义委托类型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")
}

How can I, given I have KClass<Example> , but not an instance of Example , get all properties delegated to CustomDelegate ?鉴于我有KClass<Example> ,但不是Example的实例,我怎样才能获得委托给CustomDelegate所有属性?

How can I, given I have KClass<Example>, but not an instance of Example, get all properties delegated to CustomDelegate?鉴于我有 KClass<Example>,但不是 Example 的实例,我怎样才能获得委托给 CustomDelegate 的所有属性?

You can do it in two ways depending on your needs.您可以根据需要通过两种方式进行操作。

First of all, you have to include the kotlin-reflect dependency in your build.gradle file:首先,您必须在build.gradle文件中包含kotlin-reflect依赖build.gradle

compile "org.jetbrains.kotlin:kotlin-reflect:1.1.51"

In my opinion, you should use the first solution if you can, because it's the most clear and optimized one.在我看来,如果可以,您应该使用第一种解决方案,因为它是最清晰和优化的解决方案。 The second solution instead, can handle one case that the first solution can't.相反,第二种解决方案可以处理第一种解决方案不能处理的情况。

First第一的

You can loop an the declared properties and check if the type of the property or the type of the delegate is CustomDelegate .您可以循环声明的属性并检查属性的类型或委托的类型是否为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
}

There's only one problem with this solution, you will get also the fields with type CustomDelegate , so, given this example:此解决方案只有一个问题,您还将获得类型为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")
}

You will get delegatedProperty2 and customDelegate .您将获得delegatedProperty2customDelegate If you want to get only delegatedProperty2 , I found an horrible solution that you can use if you need to manage this case.如果您只想获得delegatedProperty2 ,我找到了一个可怕的解决方案,如果您需要管理这种情况,您可以使用它。

Second第二

If you check the source code of KPropertyImpl , you can see how a delegation is implemented.如果您查看KPropertyImpl的源代码,您可以看到委托是如何实现的。 So, you can do something like this:所以,你可以做这样的事情:

// 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
}

In this case, you will get only delegatedProperty2 as result.在这种情况下,您将只获得delegatedProperty2作为结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM