dimanche 1 octobre 2017

How to get the class reference from KParameter in kotlin?

The code below is about reflection. It tries to do 2 things:

  1. case1() creates an instance from SimpleStudent class, it works.
  2. case2() creates an instance from Student class, not work.

The reason that case2() not work as well as the question, is that inside that generateValue():

  1. I don't know how to check it is kotlin type or my own type(I have a dirty way to check param.type.toString() not contain "kotlin" but I wonder if there is a better solution
  2. I don't know how to get its class reference when it's a custom class. The problem is that even though param.type.toString() == "Lesson", when I tried to get param.type::class, it's class kotlin.reflect.jvm.internal.KTypeImpl

So, how to solve it? Thanks

==============

import kotlin.reflect.KParameter
import kotlin.reflect.full.primaryConstructor
import kotlin.test.assertEquals

data class Lesson(val title:String, val length:Int)
data class Student(val name:String, val major:Lesson )
data class SimpleStudent(val name:String, val age:Int )

fun generateValue(param:KParameter, originalValue:Map<*,*>):Any? {
    var value = originalValue[param.name]

//    if (param.type is not Kotlin type){
//        // Get its ::class so that we could create the instance of it, here, I mean Lesson class?
//    }

    return value
}

fun case1(){
    val classDesc = SimpleStudent::class
    val constructor = classDesc.primaryConstructor!!

    val value = mapOf<Any,Any>(
            "name" to "Tom",
            "age" to 16
    )

    val params = constructor.parameters.associateBy (
        {it},
        {generateValue(it, value)}
    )

    val result:SimpleStudent = constructor.callBy(params)

    assertEquals("Tom", result.name)
    assertEquals(16, result.age)
}

fun case2(){
    val classDesc = Student::class
    val constructor = classDesc.primaryConstructor!!

    val value = mapOf<Any,Any>(
            "name" to "Tom",
            "major" to mapOf<Any,Any>(
                    "title" to "CS",
                    "length" to 16
            )
    )

    val params = constructor.parameters.associateBy (
        {it},
        {generateValue(it, value)}
    )

    val result:Student = constructor.callBy(params)

    assertEquals("Tom", result.name)
    assertEquals(Lesson::class, result.major::class)
    assertEquals("CS", result.major.title)
}

fun main(args : Array<String>) {
    case1()
    case2()
}





Aucun commentaire:

Enregistrer un commentaire