使用反射从注解中调用方法
Calling a method from Annotation using reflection
我有 Sample
class 和 Size
注释
case class Sample(
attr: SomeTypeA
@Size(value = 50)
name: SomeTypeB)
此 Size
注释是 class 实现 AnnotationInterface
trait AnnotationInterface[T] {
def getValue: T
}
class Size(value: Int) extends StaticAnnotation with AnnotationInterface[Int] {
override def getValue: Int = value
}
我有 Extractor
负责使用反射 class 提取成员
class Extractor[A](implicit
tt: TypeTag[A],
ct: ClassTag[A]
) { ...extract class members using reflection... }
然后我会像这样实例化提取器:
val extractor: Extractor[Sample] =
new Extractor
问题 : 如何调用 class Extractor
中的方法 getValue: T
?
如果你像
一样注释
@Size(50) name: String
而不是像
这样的元注释
@(Size @getter @setter @field)(50) name: String
然后 @Size
只保留在构造函数参数上,而不是字段,getter 或 setter。所以你需要使用 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 class(或 case-class-喜欢)然后你可以在编译时做同样的事情
import shapeless.Annotations
Annotations[Size, Sample].apply() // None :: Some(Size(50)) :: HNil
我有 Sample
class 和 Size
注释
case class Sample(
attr: SomeTypeA
@Size(value = 50)
name: SomeTypeB)
此 Size
注释是 class 实现 AnnotationInterface
trait AnnotationInterface[T] {
def getValue: T
}
class Size(value: Int) extends StaticAnnotation with AnnotationInterface[Int] {
override def getValue: Int = value
}
我有 Extractor
负责使用反射 class 提取成员
class Extractor[A](implicit
tt: TypeTag[A],
ct: ClassTag[A]
) { ...extract class members using reflection... }
然后我会像这样实例化提取器:
val extractor: Extractor[Sample] =
new Extractor
问题 : 如何调用 class Extractor
中的方法 getValue: T
?
如果你像
一样注释@Size(50) name: String
而不是像
这样的元注释@(Size @getter @setter @field)(50) name: String
然后 @Size
只保留在构造函数参数上,而不是字段,getter 或 setter。所以你需要使用 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 class(或 case-class-喜欢)然后你可以在编译时做同样的事情
import shapeless.Annotations
Annotations[Size, Sample].apply() // None :: Some(Size(50)) :: HNil