Scala 2.10 反射,如何从案例类中提取字段值,即案例类中的字段列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16079113/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:11:35  来源:igfitidea点击:

Scala 2.10 reflection, how do I extract the field values from a case class, i.e. field list from case class

scalareflectionscala-2.10case-class

提问by J Pullar

How can I extract the field values from a case class in scala using the new reflection model in scala 2.10? For example, using the below doesn't pull out the field methods

如何使用 Scala 2.10 中的新反射模型从 Scala 中的案例类中提取字段值?例如,使用下面的不会拉出字段方法

  def getMethods[T:TypeTag](t:T) =  typeOf[T].members.collect {
    case m:MethodSymbol => m
  }

I plan to pump them into

我打算将它们泵入

  for {field <- fields} {
    currentMirror.reflect(caseClass).reflectField(field).get
  }

回答by Travis Brown

MethodSymbolhas an isCaseAccessormethod that allows you to do precisely this:

MethodSymbol有一个isCaseAccessor方法可以让你精确地做到这一点:

def getMethods[T: TypeTag] = typeOf[T].members.collect {
  case m: MethodSymbol if m.isCaseAccessor => m
}.toList

Now you can write the following:

现在您可以编写以下内容:

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)

And you get only the method symbols you want.

你只得到你想要的方法符号。

If you just want the actual field name (not the valueprefix) and you want them in the same order then:

如果您只想要实际的字段名称(而不是value前缀)并且您希望它们的顺序相同,那么:

def getMethods[T: TypeTag]: List[String] =
  typeOf[T].members.sorted.collect {
    case m: MethodSymbol if m.isCaseAccessor => m.name.toString
  }

回答by Connor Doyle

If you want to get fancier you can get them in order by inspecting the constructor symbol. This code works even if the case class type in question has multiple constructors defined.

如果你想变得更漂亮,你可以通过检查构造函数符号来获得它们。即使所讨论的案例类类型定义了多个构造函数,此代码也能正常工作。

  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
    }
  }