Stub object for testing purposes fails to create via reflection:
internal fun <T : ParentThingy> KClass<in T>.random(): T {
val createViaConstructor = constructors.first()
val args = createViaConstructor.parameters.associateWith { param ->
when (param.type) {
Int::class.starProjectedType -> gen.primitive().int()
// other options omitted for brevity
else -> error("$param not supported, it's type ${param.type}")
}
}
@Suppress("UNCHECKED_CAST")
return createViaConstructor.callBy(args) as T
}
becase of:
parameter #2 serializationConstructorMarker of fun `<init>`(kotlin.Int, kotlinx.serialization.internal.SerializationConstructorMarker?): some.child.Thingy not supported, it's type kotlinx.serialization.internal.SerializationConstructorMarker?
-- the class has @Serializable
annotation. Reflection with a factory method works fine. Any ideas how to make reflection work with a primary constructor?
If you just want the primary constructor, there is a property to get that - primaryConstructor
.
val createViaConstructor = primaryConstructor ?: error(
"$this does not have a primary constructor"
)
When you use the constructors
property instead, the constructors are not guaranteed to be in any order. You can't just assume that the first one is the primary constructor.
It turns out that @Serializable
generates a secondary constructor with an extra SerializationConstructorMarker
parameter, presumably that's the constructor that will be called during deserialisation. The extra parameter is probably just there so that the two constructors have a different JVM signature. In any case, first()
ends up returning the generated constructor, not the one you want.