使用反射从注解调用方法 [英] Calling a method from Annotation using reflection
问题描述
我有带有 Size
注释的 Sample
类
I have Sample
class with Size
annotation
case class Sample(
attr: SomeTypeA
@Size(value = 50)
name: SomeTypeB)
这个Size
注解是一个实现AnnotationInterface
trait AnnotationInterface[T] {
def getValue: T
}
class Size(value: Int) extends StaticAnnotation with AnnotationInterface[Int] {
override def getValue: Int = value
}
我有 Extractor
负责使用反射提取类成员
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
问题:如何在 Extractor
类中调用方法 getValue: T
?
Question : How can I call the method getValue: T
inside the class Extractor
?
推荐答案
如果你像这样注释
@Size(50) name: String
而不是像
@(Size @getter @setter @field)(50) name: String
then @Size
仅保留在构造函数参数上,而不是字段、getter 或 setter.所以你需要使用A
的构造函数.
then @Size
remains only on constructor parameter, not field, getter or setter. So you need to use constructor of A
.
试试
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
}
}
如果您需要value
或
import scala.tools.reflect.ToolBox
val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
tb.eval(tb.untypecheck(annotationTree)).asInstanceOf[Size].getValue //50
如果你真的想调用 getValue
.
顺便说一下,如果您可以访问 Size
并且可以将其设置为 case 类(或 case-class-like),那么您可以在大多数情况下执行相同的操作编译时间
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
这篇关于使用反射从注解调用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!