如何在Scala 2.10.1中通过反射获得ctor参数类型

如何在Scala 2.10.1中通过反射获得ctor参数类型,scala,reflection,Scala,Reflection,我想做的应该很简单。我想。我想使用反射来确定案例类构造函数的参数的名称和类型。下面是一个REPL交互。您可以跳到调用“params”的末尾。我想检查或模式匹配内部列表中的符号,以确定“name”确实是一个字符串,“age”是一个Int 我该怎么做 scala> case class Person(name: String, age: Int) defined class Person scala> import scala.reflect.runtime.universe._ im

我想做的应该很简单。我想。我想使用反射来确定案例类构造函数的参数的名称和类型。下面是一个REPL交互。您可以跳到调用“params”的末尾。我想检查或模式匹配内部列表中的符号,以确定“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))

有趣的是你应该问!这正是我现在正在做的

所以,首先,你有情人。因此,您必须处理如何/是否支持多个参数列表。下面是一些坚持只使用一个参数列表的代码,并捕获了以下内容:

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 );

我现在仍在努力,但到目前为止,这些都在为我工作。祝你好运

这就是获得表示构造函数参数类型的
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 ?
typeOfNameParam=:=typeOf[Int]//此类型是Int吗?
typeOfNameParam使用:

scala>import net.fwbrasil.smirror_
导入net.fwbrasil.smirror_
scala>隐式val mirror=scala.reflect.runtime.currentMirror
镜像:reflect.runtime.universe.mirror=JavaMirror和scala.t。。。
scala>案例类人物(姓名:String,年龄:Int)
限定类人
scala>val clazz=sClassOf[人]
clazz:net.fwbrasil.smiror.SClass[Person]=Person
scala>val ctor=clazz.constructors.head
ctor:net.fwbrasil.smirror.sconstuctor[Person]=(名称:java.lang.String,年龄:scala.Int):Person
scala>ctor.parameters
res0:List[ctor.SParameterType]=List(名称:java.lang.String,年龄:scala.Int)
scala>ctor.parameters.head.sClass==sClassOf[String]
res2:Boolean=true

非常感谢。对此困惑了一会儿。除了与ScalaDoc链接的文档外,您还发现了其他文档吗?这里有一个关于Scala反射的指南:我发现这篇指南非常有用:但总而言之,反射和宏的所有内容都是反复尝试的(偶尔还有堆栈溢出问题!)。请注意,运行时(与宏相反)反射是非常不安全的:在我理解这一点之前,我在随机奇异性上浪费了很多时间。我不认为有任何方法可以尝试通过反射将值强制转换为所选类型?Low等于:val a:Any=2;val i=a.asInstanceOf[Int]这可以通过反射来完成吗?@billbarington我不明白。类型转换是一个编译时操作,所以“通过反射转换”对我来说没有意义(除非你只是指类型检查)。你需要它做什么?你认为它看起来怎么样?是的,这更多的是因为我对如何实现我最初设想的困惑。我只是想通过反射检查一个case类,并使用映射中的值创建一个实例,其中映射键是ctor参数的名称。我已经意识到我真的不需要这样做(出于我的目的),但我不清楚如何通过反射来实现这一点。似乎您必须以某种方式分离实例的构造和它的(只读)字段的填充?但是你是对的,我的问题在给定的上下文中没有意义。很抱歉。
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