2013-10-01 31 views
6

我有一個對象,看起來像這樣:如何在Scala中使用反射來獲取所有對象的vals和subobject vals?

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])和接收的哈希)所有我的對象已經聲明瞭瓦爾斯的:

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

回答

8

這裏整潔的事情是,你使用恆定值定義(即最終值沒有類型註釋;見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情況與實例鏡子, 但基本的工作方式,以遞歸收集從子對象的鍵值對會是相同的。

+0

這是非常有效的。謝謝! –

+0

@TravisBrown:我怎樣才能讓它對非最終成員有效? –

+1

@VenkatSudheerReddyAedama可能值得一個新的問題 - 如果你發佈一個,我可以嘗試今晚看看。 –

相關問題