Calling a method from Annotation using reflection

大城市里の小女人 提交于 2021-02-05 11:25:26

问题


I have Sample class with Size annotation

case class Sample(
  attr: SomeTypeA
  @Size(value = 50)
  name: SomeTypeB)

This Size annotation is a class that implements AnnotationInterface

trait AnnotationInterface[T] {
  def getValue: T
}

class Size(value: Int) extends StaticAnnotation with AnnotationInterface[Int] {
    override def getValue: Int = value
}

And I have Extractor which is responsible for extracting class members using reflection

class Extractor[A](implicit
    tt: TypeTag[A],
    ct: ClassTag[A]
) { ...extract class members using reflection... } 

Then I would instantiate the extractor like:

val extractor: Extractor[Sample] =
      new Extractor 

Question : How can I call the method getValue: T inside the class Extractor ?


回答1:


If you annotate like

@Size(50) name: String

rather than with meta-annotations like

@(Size @getter @setter @field)(50) name: String

then @Size remains only on constructor parameter, not field, getter or setter. So you need to use constructor of A.

Try

class Extractor[A](implicit
                   tt: TypeTag[A],
                   ct: ClassTag[A]
                  ) {
  val annotationTree = typeOf[A]
    .decl(termNames.CONSTRUCTOR).asMethod
    .paramLists.flatten
    .flatMap(_.annotations)
    .map(_.tree)
    .filter(_.tpe =:= typeOf[Size])
    .head 

  annotationTree match {
    case q"new $_($value)" => println(value) //50
  }
}

if you need the value or

import scala.tools.reflect.ToolBox
val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()

tb.eval(tb.untypecheck(annotationTree)).asInstanceOf[Size].getValue //50

if you really want to call getValue.

By the way, if you have access to Size and can make it a case class (or case-class-like) then you can do the same mostly at compile time

import shapeless.Annotations

Annotations[Size, Sample].apply() // None :: Some(Size(50)) :: HNil


来源:https://stackoverflow.com/questions/62343008/calling-a-method-from-annotation-using-reflection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!