Reflexión de Scala 2.10, ¿cómo extraigo los valores de campo de una clase de caso
reflection scala-2.10 (2)
Si quieres ser más elegante, puedes ordenarlos inspeccionando el símbolo del constructor. Este código funciona incluso si el tipo de clase de caso en cuestión tiene múltiples constructores definidos.
import scala.collection.immutable.ListMap
import scala.reflect.runtime.universe._
/**
* Returns a map from formal parameter names to types, containing one
* mapping for each constructor argument. The resulting map (a ListMap)
* preserves the order of the primary constructor''s parameter list.
*/
def caseClassParamsOf[T: TypeTag]: ListMap[String, Type] = {
val tpe = typeOf[T]
val constructorSymbol = tpe.decl(termNames.CONSTRUCTOR)
val defaultConstructor =
if (constructorSymbol.isMethod) constructorSymbol.asMethod
else {
val ctors = constructorSymbol.asTerm.alternatives
ctors.map(_.asMethod).find(_.isPrimaryConstructor).get
}
ListMap[String, Type]() ++ defaultConstructor.paramLists.reduceLeft(_ ++ _).map {
sym => sym.name.toString -> tpe.member(sym.name).asMethod.returnType
}
}
¿Cómo puedo extraer los valores de campo de una clase de caso en scala usando el nuevo modelo de reflexión en scala 2.10? Por ejemplo, el uso de lo siguiente no elimina los métodos de campo
def getMethods[T:TypeTag](t:T) = typeOf[T].members.collect {
case m:MethodSymbol => m
}
Planeo bombearlos a
for {field <- fields} {
currentMirror.reflect(caseClass).reflectField(field).get
}
MethodSymbol
tiene un método isCaseAccessor
que le permite hacer precisamente esto:
def getMethods[T: TypeTag] = typeOf[T].members.collect {
case m: MethodSymbol if m.isCaseAccessor => m
}.toList
Ahora puedes escribir lo siguiente:
scala> case class Person(name: String, age: Int)
defined class Person
scala> getMethods[Person]
res1: List[reflect.runtime.universe.MethodSymbol] = List(value age, value name)
Y obtienes solo los símbolos de método que deseas.