我如何使用Scala中的反射来获取所有对象val和subobject vals? [英] How can I get all object vals and subobject vals using reflection in Scala?

查看:714
本文介绍了我如何使用Scala中的反射来获取所有对象val和subobject vals?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  object设置{
final val Host =host
final val Protocol =protocol

对象用户{
最终val名称=用户名
最终val密码=密码
}

object Subject {
final val Query =query
final val Predicate =predicate
}
}

我想要做的就像 membersAsHash(classOf [CollectionSettings])并接收一个哈希),我已经在对象中声明了所有val:

  [
Host => 主机,
协议=> protocol,
Name => 用户名,
密码=> password,
Query => query,
Predicate => 谓词
]

如果键是一个字符串,完整的包名称(例如com.example.Settings.User)。我真正需要的是价值观,所以如果我只能得到它,它仍然是可以接受的。



这已经让我成为子对象的名称,但是我不能似乎弄清楚如何获得每个内部的vals:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ import $ sc $。 reflect.runtime。{universe => ()。}}
val mirror = ru.runtimeMirror(getClass.getClassLoader)
val subObjects = ru.typeOf [CollectionSettings.type] .declarations.filter(_。isModule)
subobjects.map(o => mirror.reflectModule(o.asModule).instance.asInstanceOf [Object] .toString).toList
}


解决方案

这里的巧妙之处在于您使用了常量值定义(即,没有类型注释的最终值;参见§4.1 语言规范),所以你甚至不需要任何镜像:

  def deepMembers [A:scala.reflect.runtime.universe.TypeTag](a:A)= {
import scala.reflect .runtime.universe._

def成员(s:Symbol):Map [String,String] =
s.typeSignature.declarations.collect {
case m:ModuleSymbol = >成员(m)
案例m:MethodSymbol if m.isAccessor => m.returnType match {
case ConstantType(Constant(s:String))=> Map(m.name.decoded - > s)
case _ => Map.empty [String,String]
}
} .foldLeft(Map.empty [String,String])(_ ++ _)

成员(typeOf [A] .termSymbol)
}

它是这样工作的:

  scala> deepMembers(设置)foreach println 
(名称,用户名)
(谓词,谓词)
(查询,查询)
(密码,密码)
(协议,协议)
(主机,主机)

如果由于某种原因,您无法使用常数值定义,您需要调整 MethodSymbol 大小写以处理实例镜像
,但从子对象递归收集键值对的基本方法是相同。


I have an object that looks like this:

object Settings {
  final val Host = "host"
  final val Protocol = "protocol"

  object User {
    final val Name = "username"
    final val Password = "password"
  }

  object Subject {
    final val Query = "query"
    final val Predicate = "predicate"
  }
}

What I'd like to do is something like membersAsHash(classOf[CollectionSettings]) and receive a hash) of all of the vals that I've declared in the object:

[
  Host => "host", 
  Protocol => "protocol", 
  Name => "username",
  Password => "password",
  Query => "query",
  Predicate => "predicate"
]

It'd be fine if the key was a string, even the full package name (e.g. com.example.Settings.User). What I really need is the values, so if I can only get that, it's still acceptable.

This has gotten me the name of the subobjects, but I can't seem to figure out how to get the vals that are internal to each:

val optionsToCheck = {
  import scala.reflect.runtime.{universe => ru}
  val mirror = ru.runtimeMirror(getClass.getClassLoader)
  val subObjects = ru.typeOf[CollectionSettings.type].declarations.filter(_.isModule)
  subobjects.map(o => mirror.reflectModule(o.asModule).instance.asInstanceOf[Object].toString).toList
}

解决方案

The neat thing here is that you're using constant value definitions (i.e., final values with no type annotation; see §4.1 of the language specification), so you don't even need any mirrors:

def deepMembers[A: scala.reflect.runtime.universe.TypeTag](a: A) = {
  import scala.reflect.runtime.universe._

  def members(s: Symbol): Map[String, String] =
    s.typeSignature.declarations.collect {
      case m: ModuleSymbol => members(m)
      case m: MethodSymbol if m.isAccessor => m.returnType match {
        case ConstantType(Constant(s: String)) => Map(m.name.decoded -> s)
        case _ => Map.empty[String, String]
      }
    }.foldLeft(Map.empty[String, String])(_ ++ _)

  members(typeOf[A].termSymbol)
}

It works like this:

scala> deepMembers(Settings) foreach println
(Name,username)
(Predicate,predicate)
(Query,query)
(Password,password)
(Protocol,protocol)
(Host,host)

If for some reason you couldn't use constant value definitions, you'd need to adjust the MethodSymbol case to work with instance mirrors, but the basic approach to recursively collecting key-value pairs from child objects would be the same.

这篇关于我如何使用Scala中的反射来获取所有对象val和subobject vals?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆