Как вывести список всех полей с пользовательской аннотацией, используя отражение Scala во время выполнения?

У меня есть пользовательская аннотация, например

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

Как для данного класса я могу перечислить все его поля, которые имеют эту аннотацию? Я ищу что-то вроде (просто догадываюсь):

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

person Petr    schedule 22.07.2013    source источник


Ответы (1)


Это можно сделать с помощью TypeTag, отфильтровав members вашего типа ввода:

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
}

Затем:

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("")))

Это дает вам не MyProperty, а universe.Annotation. У него есть метод scalaArgs, который дает вам доступ к его аргументам в виде деревьев, если вам нужно что-то с ними сделать.

person gourlaysama    schedule 22.07.2013