2013-04-18 70 views
25

如何使用scala 2.10中的新反射模型從scala中的案例類提取字段值? 例如,使用下面的不拔出場方法Scala 2.10反射,如何從案例類中提取字段值

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

我打算將它們泵入

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

回答

39

MethodSymbol有一個isCaseAccessor方法,它允許你這樣做正是這樣:

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

現在您可以編寫以下內容:

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) 

而你只得到你想要的方法符號。

+0

啊我現在意識到我的方法是錯誤的。任何想法如何從一個未知案例類獲取caseAccessors? IE之一,目前存儲爲val SomeCaseClass:任何 –

+0

等待,沒有得到它 currentMirror.reflect(someCaseClass).symbol.asType.typeSignature.members –

+0

可以在scala 2.10下使用多線程環境嗎? – jilen

10

如果您想要更有趣,可以通過檢查構造函數符號來獲得它們。即使有問題的案例類類型有多個定義的構造函數,此代碼也可以工作。

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

我在'constructorSymbol.asTerm.alternatives'表達式中發現了'scala.ScalaReflectionException:不是一個術語'的情況。 'declaration'的文檔註釋是指'OverloadedSymbol',但是似乎沒有這樣的實體存在。 –

+0

事實證明,發生這種情況的原因是因爲我使用'this.type'從用作所討論案例類的超類型的特徵調用它。 –

+0

另外,'case class P(i:Int)(j:Int)'。 –

相關問題