Skip to content

Instantly share code, notes, and snippets.

@gzoller
Last active August 29, 2015 14:16
Show Gist options
  • Save gzoller/9158363115a6bcd646f5 to your computer and use it in GitHub Desktop.
Save gzoller/9158363115a6bcd646f5 to your computer and use it in GitHub Desktop.
Problem creating object from reflected constructor in Scala
package co.blocke.m2
import scala.reflect.runtime.currentMirror
import scala.reflect.runtime.universe._
case class PField( fieldName:String )
case class PCaseClass( name:String, fields:List[PField], ctor:MethodMirror )
// sample case classes
case class Simple(a:String, b:Int, c:Boolean)
class Inner(val underlying: String) extends AnyVal
case class Complex( hey:Inner, you:String )
object Poof extends App {
private def poof( cc:PCaseClass, data:Map[String,Any] ) : Any = {
// Get constructor arguments in right order, we should.
val args = cc.fields.collect{ case f => data.get(f.fieldName).getOrElse(None) }
println(s"::: Poof : ${cc.name} with "+args.toList)
println( "--- Ctor : "+cc.ctor)
println( "--- Args : "+args.toList.map(_.getClass.getName))
println( "--- Tried: "+scala.util.Try( cc.ctor.apply(args:_*) ))
cc.ctor.apply( args: _* )
}
def getCtor[T]()(implicit tt:TypeTag[T]) : MethodMirror = {
val classSymbol = tt.tpe.typeSymbol.asClass
val ctor = classSymbol.primaryConstructor
val classMirror = currentMirror.reflectClass(classSymbol)
classMirror.reflectConstructor(ctor.asMethod)
}
//---------------------------
val one = PCaseClass("co.blocke.m2.Simple", List(PField("a"),PField("b"),PField("c")), getCtor[Simple]())
println(poof(one, Map("a"->"Wow","b"->5,"c"->true)).asInstanceOf[Simple])
println("--------------------------------")
val two = PCaseClass("co.blocke.m2.Complex", List(PField("hey"),PField("you")), getCtor[Complex]())
println(poof(two, Map("hey"->new Inner("ok"),"you"->"wow")).asInstanceOf[Complex])
println(Complex(new Inner("ok"),"wow")) // comparison with direct value class instantiation
}
/* OUTPUT WHEN RUN
--- Ctor : constructor mirror for def <init>(a: String,b: scala.Int,c: scala.Boolean): co.blocke.m2.Simple (bound to null)
--- Args : List(java.lang.String, java.lang.Integer, java.lang.Boolean)
--- Tried: Success(Simple(Wow,5,true))
Simple(Wow,5,true)
--------------------------------
::: Poof : co.blocke.m2.Complex with List(co.blocke.m2.Inner@ddc, wow)
--- Ctor : constructor mirror for def <init>(hey: co.blocke.m2.Inner,you: String): co.blocke.m2.Complex (bound to null)
--- Args : List(co.blocke.m2.Inner, java.lang.String)
--- Tried: Success(Complex(co.blocke.m2.Inner@ddc,null))
Complex(co.blocke.m2.Inner@ddc,null)
Complex(co.blocke.m2.Inner@ddc,wow)
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment