我想做的事情应该非常简单。我认为。我想使用反射来确定case类构造函数的参数的名称和类型。以下是REPL互动。你可以跳到最后调用'paramss'的地方。我想检查或模式匹配内部列表中的符号,以确定'name'确实是一个字符串,'age'是一个Int。
我该怎么做?
scala> case class Person(name: String, age: Int)
defined class Person
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> typeOf[Person]
res0: reflect.runtime.universe.Type = Person
scala> typeTag[Person]
res1: reflect.runtime.universe.TypeTag[Person] = TypeTag[Person]
scala> res1.mirror
res2: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@2daf73a4 of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [(memory)] and parent being scala.tools.nsc.util.ScalaClassLoader$URLClassLoader@59d12b6a of type class scala.tools.nsc.util.ScalaClassLoader$URLClassLoader with classpath [file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/jre/lib/resources.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/jre/lib/rt.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/jre/lib/jsse.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/jre/lib/jce.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/j...
scala> res1.tpe
res3: reflect.runtime.universe.Type = Person
scala> res3.typeSymbol.asClass
res4: reflect.runtime.universe.ClassSymbol = class Person
scala> res2.reflectClass(res4)
res5: reflect.runtime.universe.ClassMirror = class mirror for Person (bound to null)
scala> res3.declaration(reflect.runtime.universe.nme.CONSTRUCTOR)
res6: reflect.runtime.universe.Symbol = constructor Person
scala> res6.asMethod
res7: reflect.runtime.universe.MethodSymbol = constructor Person
scala> res7.paramss
res8: List[List[reflect.runtime.universe.Symbol]] = List(List(value name, value age))
答案 0 :(得分:1)
这就是你得到一个表示构造函数参数类型的Type
对象的方法:
val ctorParamss = typeOf[Person].member(nme.CONSTRUCTOR).asMethod.paramss
val typeOfNameParam: Type = paramss(0)(0).typeSignature
现在您拥有该对象,您可以对其执行各种测试:
typeOfNameParam =:= typeOf[Int] // is this type an Int ?
typeOfNameParam <:< typeOf[Number] // is this type java.lang.Number or its subtype ?
答案 1 :(得分:1)
使用SMirror:
scala> import net.fwbrasil.smirror._
import net.fwbrasil.smirror._
scala> implicit val mirror = scala.reflect.runtime.currentMirror
mirror: reflect.runtime.universe.Mirror = JavaMirror with scala.t...
scala> case class Person(name: String, age: Int)
defined class Person
scala> val clazz = sClassOf[Person]
clazz: net.fwbrasil.smirror.SClass[Person] = Person
scala> val ctor = clazz.constructors.head
ctor: net.fwbrasil.smirror.SConstructor[Person] = <init>(name: java.lang.String, age: scala.Int): Person
scala> ctor.parameters
res0: List[ctor.SParameterType] = List(name: java.lang.String, age: scala.Int)
scala> ctor.parameters.head.sClass == sClassOf[String]
res2: Boolean = true
答案 2 :(得分:0)
有趣的你应该问!这正是我现在正在做的事情。
所以,首先,你有paramss。因此,您必须处理如何/是否支持多个参数列表。这里有一些代码坚持一个参数列表,并捕获:
val ctorParams : List[Symbol] = ctorParamss match {
case Nil => {
println("Warning: Trying to populate a no-arg constructor from a Map. No data will be used.");
Nil;
}
case head :: Nil => head;
case _ => throw new UnsupportedOperationException("Cannot populate a constructor with multiple param lists from a Map.");
}
现在我们需要名称和类型名称:
val ctorParamNames = ctorParams.map( _.name.toString.trim );
val ctorParamTypeNames = ctorParams.map( _.typeSignature.baseClasses(0).fullName.toString.trim );
在这个时刻,我还在努力解决这个问题,但到目前为止,这对我很有帮助。祝你好运!