Accessing an Annotation Value in Scala

后端 未结 3 1517
予麋鹿
予麋鹿 2020-12-16 20:10

TL;DR: Basically, I\'m looking for the Scala equivalent of the Java:

(MyAnnotation) Thing.getClass().getAnnotations()[0]

D

3条回答
  •  抹茶落季
    2020-12-16 20:34

    Without having to depend on scala-compiler, this is my version:

      def fetchAnnotations[T <: Annotation](cls : Class[_]) : List[T]= {
        import scala.reflect.runtime.universe._
        val mirror = runtimeMirror(cls.getClassLoader)
        val clsSymbol = mirror.staticClass(cls.getCanonicalName)
        val annotations = clsSymbol.annotations
    
        val res = ListBuffer[T]()
        for(annt : Annotation <- annotations) {
          val anntCls = annt.tree.tpe.typeSymbol.asClass
          val classMirror = mirror.reflectClass(anntCls);
          val anntType = annt.tree.tpe
          val constructor = anntType.decl(termNames.CONSTRUCTOR).asMethod;
          val constructorMirror = classMirror.reflectConstructor(constructor);
    
          val instance = annt.tree match {
            case Apply(c, args : List[Tree])   =>
              val res = args.collect({
                case i: Tree =>
                  i match {
                    case Literal(Constant(value)) =>
                      value
                  }
              })
              constructorMirror(res: _*).asInstanceOf[T]
          }
    
          res+=(instance)
        }
        res.toList
      }
    

    The previous code will only work when the arguments are primitive I suspect.

    If we can afford depending on scala-compiler, then we can do something like:

    def fetchAnnotations_toolBox[T <: Annotation](cls : Class[_]) : List[T]= {
        import scala.reflect.runtime.universe._
        val mirror = runtimeMirror(cls.getClassLoader)
        val clsSymbol = mirror.staticClass(cls.getCanonicalName)
        val annotations = clsSymbol.annotations
    
        val res = ListBuffer[T]()
        for(annt : Annotation <- annotations) {
          import scala.tools.reflect.ToolBox
    
          val toolbox = mirror.mkToolBox()
          val instance = toolbox.eval(toolbox.untypecheck(toolbox.typecheck(annt.tree))).asInstanceOf[T]
          res+=(instance)
        }
        res.toList
      }
    

提交回复
热议问题