Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Forked from takezoux2/ReflectionSample.scala
Created December 19, 2012 13:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuwei-k/4336627 to your computer and use it in GitHub Desktop.
Save xuwei-k/4336627 to your computer and use it in GitHub Desktop.
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-reflect" % )
scalaVersion := "2.10.0-RC5"
import scala.reflect.runtime.universe._
import scala.reflect._
object App{
def main(args : Array[String]){
val m = toMap(User("Kudo",2,false))
println(m)
//Map(admin_? -> false, gender -> 2, name -> Kudo)
val u = new User()
fromMap(u,Map("name" -> "Riki","gender" -> "1","admin_?" -> "true"))
println(u)
//User(Riki,1,true)
}
def toMap[T](v : T)(implicit tt : TypeTag[T],ct : ClassTag[T]):Map[String,String] = {
// var だけを抽出
val vars = typeOf[T].members.filter{
case t : TermSymbol => t.isVar
}
// Reflection実行のためのMirrorを取得
val mirror = tt.mirror // runtimeMirror(getClass.getClassLoader)でもOK
// インスタンス操作のためのReflectionを取得
val rf = mirror.reflect(v)
vars.map{
case v : TermSymbol =>
// GetterMethodを取得
val getterMethod = rf.reflectMethod(v.getter.asMethod)
( v.name.decoded.trim -> getterMethod().toString) //nameを取得すると末尾にスペースが入るのでtrimしておく
}.toMap
}
def fromMap[T]( v : T , map : Map[String,String] )(implicit tt : TypeTag[T],ct : ClassTag[T]):T = {
// var だけを抽出
val vars = typeOf[T].members.filter{
case t : TermSymbol => t.isVar
}
// Reflection実行のためのMirrorを取得
val mirror = tt.mirror // runtimeMirror(getClass.getClassLoader)でもOK
// インスタンス操作のためのReflectionを取得
val rf = mirror.reflect(v)
vars.foreach{
case t : TermSymbol =>
map.get(t.name.decoded.trim) match{
case Some(v) =>{
val setterMethod = rf.reflectMethod(t.setter.asMethod)
// 型に合わせて変換
t.getter.asMethod.returnType match{
case t if t =:= typeOf[String] =>
setterMethod(v)
// Primitive型は、JavaUniverse.definitionsに定義されている
case definitions.IntTpe =>
setterMethod(v.toInt)
case definitions.BooleanTpe =>
setterMethod(v.toBoolean)
case t => println("Unknown type " + t)
}
}
case None => println("Value not found:" + t.name.decoded)
}
}
v
}
}
case class User(var name : String,var gender : Int,var admin_? : Boolean){
def this() = this("",1,false)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment