Last active
December 9, 2015 18:39
-
-
Save takezoux2/4311905 to your computer and use it in GitHub Desktop.
Sample code for scala reflection.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]) = { | |
val t = typeOf[T] | |
// var だけを抽出 | |
val vars = t.members.filter( _ match{ | |
case t : TermSymbol => t.isVar | |
case _ => false | |
}) | |
// Reflection実行のためのMirrorを取得 | |
val mirror = tt.mirror // runtimeMirror(getClass.getClassLoader)でもOK | |
// インスタンス操作のためのReflectionを取得 | |
val rf = mirror.reflect(v) | |
var fieldValues : Map[String,String] = Map.empty | |
vars.foreach( v => v match{ | |
case v : TermSymbol => { | |
// GetterMethodを取得 | |
val getterMethod = rf.reflectMethod(v.getter.asMethod) | |
fieldValues += ( v.name.decoded.trim -> getterMethod().toString) //nameを取得すると末尾にスペースが入るのでtrimしておく | |
} | |
}) | |
fieldValues | |
} | |
def fromMap[T]( v : T , map : Map[String,String] )(implicit tt : TypeTag[T],ct : ClassTag[T]) = { | |
val t = typeOf[T] | |
// var だけを抽出 | |
val vars = t.members.filter( _ match{ | |
case t : TermSymbol => t.isVar | |
case _ => false | |
}) | |
// Reflection実行のためのMirrorを取得 | |
val mirror = tt.mirror // runtimeMirror(getClass.getClassLoader)でもOK | |
// インスタンス操作のためのReflectionを取得 | |
val rf = mirror.reflect(v) | |
vars.foreach( v => v match{ | |
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
ちょっとリファクタした
https://gist.github.com/4336627