2017-10-22 1 views
2

Access property delegate in Kotlin은 인스턴스에서 대리인에 액세스하는 방법입니다. Kotlin 1.1부터 KProperty::getDelegate을 사용할 수 있지만 위임의 인스턴스를 반환하므로 클래스의 인스턴스가 먼저 필요합니다.인스턴스가없는 Kotlin 대리인 유형에 액세스

이제 클래스 인스턴스가 없어도 대리자 유형을 가져 오려고합니다. 의는 CustomDelegate의 인스턴스에 위임 클래스의 모든 속성을 얻으려면 사용자 정의 대리자 형식 CustomDelegate 도서관을 고려

내가, 내가 KClass<Example>을 제공하지만, Example 아닌 인스턴스 수있는 방법
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") 
} 

, CustomDelegate에 위임 된 모든 속성을 가져 옵니까?

답변

2
내가, 내가 KClass < 예 >이 주어진하지만 예의 인스턴스, CustomDelegate에 위임 된 모든 속성을 얻을 수있는 방법

?

필요에 따라 두 가지 방법으로 수행 할 수 있습니다. 그것이 가장 분명하기 때문에,

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

제 생각에는, 첫 번째 솔루션 당신이 할 수있는 경우를 사용해야합니다 : 모든

첫째, 당신은이 당신의 build.gradle 파일에 의존성을 코 틀린-반영 포함해야 최적화 된 것. 두 번째 솔루션 대신 첫 번째 솔루션이 처리 할 수없는 한 가지 경우를 처리 할 수 ​​있습니다.

먼저

당신이 할 수있는 루프 선언 된 속성과 속성 또는 대리자의 종류의 타입이 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" } ?: [email protected] false 
     } catch (t: Throwable) { 
      // Catch KotlinReflectionInternalError. 
      [email protected] 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 결과를 얻을 것이다.

+0

첫 번째 솔루션을 사용하면 위임 필드와 위임 필드를 매핑 할 수 있습니까? 위임 된 프로퍼티는 모두 하나의 인터페이스를 상속해야하므로 'delegatedProperty2' 만 반환하면됩니다. – msrd0

+0

@ msrd0 예, 가능합니다. 'CustomDelegate :: class.java == property.javaField? .type' 조건을'CustomDelegate :: class.java == property.javaField? .type && property.returnType '조건으로 변경할 수 있습니다.isSubtypeOf (MyInterface :: class.starProjectedType)' –