Calling a method from Annotation using reflection

前端 未结 1 1321
甜味超标
甜味超标 2021-01-28 07:07

I have Sample class with Size annotation

case class Sample(
  attr: SomeTypeA
  @Size(value =         


        
1条回答
  •  滥情空心
    2021-01-28 07:51

    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
    

    0 讨论(0)
提交回复
热议问题