如何在Scala中使用反射获取所有对象值和子对象值?
发布时间:2020-12-16 18:59:42 所属栏目:安全 来源:网络整理
导读:我有一个看起来像这样的对象: 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 Predica
我有一个看起来像这样的对象:
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" } } 我想做的是像membersAsHash(classOf [CollectionSettings])并接收我在对象中声明的所有val的哈希值: [ Host => "host",Protocol => "protocol",Name => "username",Password => "password",Query => "query",Predicate => "predicate" ] 如果密钥是一个字符串,即使是完整的包名称(例如com.example.Settings.User)也没关系.我真正需要的是价值观,所以如果我只能得到它,它仍然可以接受. 这让我得到了子对象的名称,但我似乎无法弄清楚如何获取每个子对象的内部值: 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 } 解决方法
这里的好处是你使用常量值定义(即没有类型注释的最终值;参见
language specification的§4.1),所以你甚至不需要任何镜像:
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) } 它的工作原理如下: scala> deepMembers(Settings) foreach println (Name,username) (Predicate,predicate) (Query,query) (Password,password) (Protocol,protocol) (Host,host) 如果由于某种原因您无法使用常量值定义,则需要调整MethodSymbol案例以使用实例镜像,但是从子对象递归收集键值对的基本方法是相同的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |