2013-07-22 7 views
6

Ich habe eine benutzerdefinierte Anmerkung wieWie listet man alle Felder mit einer benutzerdefinierten Anmerkung auf, wenn man die Scala-Reflexion zur Laufzeit verwendet?

class MyProperty(val name: String) 
    extends annotation.StaticAnnotation; // or should I extend something else? 

Für eine bestimmte Klasse, wie kann ich alle seine Felder auflisten, die diese Anmerkung haben? Ich bin auf der Suche nach so etwas wie (nur raten):

def listProperties[T: ClassTag]: List[(SomeClassRepresentingFields,MyProperty)]; 

Antwort

11

Dies kann mit einem TypeTag getan werden, durch Filterung durch die members Ihren Eingabetyp:

import reflect.runtime.universe._ 

def listProperties[T: TypeTag]: List[(TermSymbol, Annotation)] = { 
    // a field is a Term that is a Var or a Val 
    val fields = typeOf[T].members.collect{ case s: TermSymbol => s }. 
    filter(s => s.isVal || s.isVar) 

    // then only keep the ones with a MyProperty annotation 
    fields.flatMap(f => f.annotations.find(_.tpe =:= typeOf[MyProperty]). 
    map((f, _))).toList 
} 

Dann:

scala> class A { @MyProperty("") val a = 1 ; @MyProperty("a") var b = 2 ; 
    var c: Long = 1L } 
defined class A 

scala> listProperties[A] 
res15: List[(reflect.runtime.universe.TermSymbol, reflect.runtime.universe.Annotation)] 
    = List((variable b,MyProperty("a")), (value a,MyProperty(""))) 

Dies gibt Ihnen nicht direkt eine MyProperty, sondern eine universe.Annotation. Es hat eine scalaArgs Methode, die Ihnen Zugriff auf seine Argumente als Bäume gibt, wenn Sie etwas mit dann tun müssen.