後日、もう少しバージョンアップします。
やりたい事は、ScalaのReflectionを使ってクラスのコンストラクタを取得して新しいインスタンスを作るです。
case classも、これでパラメータの取得が可能です。
build.sbt
scalaVersion := "2.10.0" libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.10.0"App.scala
import scala.reflect.runtime.universe._
import scala.reflect._
case class Hoge(val name : String)
object App{
def main(args : Array[String] ) {
println(newFromParamsMap[Hoge](Map("name" -> "hoge")))
}
def newFromParamsMap[T](params : Map[String,Any])(implicit tt : TypeTag[T],ct : ClassTag[T]) : T = {
val t = typeOf[T]
// Primary constructorの取得
val primaryConstructor = t.declarations.collectFirst({
case m : MethodSymbol if m.isPrimaryConstructor => m
})
if(!primaryConstructor.isDefined){
throw new Exception(s"Class ${t} doesn't have primary constructor.")
}
//コンストラクタのパラメーターを取得してくる
//後日型のチェック機能も入れます。
val constructorValues = primaryConstructor.get.paramss.map( _params => {
_params.map( {
case t : TermSymbol => {
val p = params(t.name.encoded.trim)
/*if( ! t.typeSignatur =:= typeOf(p.getClass){
throw new Exception("Parameter :${t.name.encoded} doesn't match type!)
}*/
p
}
})
})
// 実行のためのMirror取得
val mirror = tt.mirror
val classMirror = mirror.reflectClass(t.typeSymbol.asClass)
val constructorMirror = classMirror.reflectConstructor(primaryConstructor.get)
constructorMirror(constructorValues.flatten :_*).asInstanceOf[T]
}
}