samedi 21 février 2015

How to use reflect to get annotation instance in scala 2.11

I want get annotation instance by reflect , I have tried to use this method link but it doesn't work.


It will be success when annotation field type is basic and without default value,but when the type is complex or has default value , it will be fail.


In my code like:



import org.scalatest.FunSuite

import scala.annotation.StaticAnnotation
import scala.reflect.runtime.universe._

object ReflectHelper {

val runtime = runtimeMirror(getClass.getClassLoader)

/**
* @param beanClazz target bean class
* @tparam A target annotation
* @return annotation instances
*/
def getClassAnnotation[A: TypeTag](beanClazz: Class[_]): Option[A] = {
val typeAnnotation = typeOf[A]
scala.reflect.runtime.currentMirror.classSymbol(beanClazz).toType.typeSymbol.asClass.annotations.find(a => a.tree.tpe == typeAnnotation).map {
annotation =>
/*
* Has error : scala.reflect.internal.Trees$Select cannot be cast to scala.reflect.api.Constants$ConstantApi
* when annotation field use default value
*
* Has error : scala.reflect.internal.Trees$TypeApply cannot be cast to scala.reflect.api.Constants$ConstantApi
* when annotation field type is collection
*/
val value = annotation.tree.children.tail.map(_.productElement(0).asInstanceOf[Constant].value)
runtime.reflectClass(typeAnnotation.typeSymbol.asClass).
reflectConstructor(typeAnnotation.decl(termNames.CONSTRUCTOR).asMethod)(value: _*).
asInstanceOf[A]
}
}

}

case class Entity1(idField: String = "id") extends StaticAnnotation

case class Entity2(rels: List[String] = List()) extends StaticAnnotation

@Entity1(idField = "pk")
case class Test1Entity()

@Entity1()
case class Test2Entity()

@Entity2(rels = List("fieldA"))
case class Test3Entity()

class Test extends FunSuite {
test("Bean Test") {
//Success
assert(ReflectHelper.getClassAnnotation[Entity1](classOf[Test1Entity]).get.idField == "pk")
//Error : scala.reflect.internal.Trees$Select cannot be cast to scala.reflect.api.Constants$ConstantApi
assert(ReflectHelper.getClassAnnotation[Entity1](classOf[Test2Entity]).get.idField == "id")
//Error : scala.reflect.internal.Trees$TypeApply cannot be cast to scala.reflect.api.Constants$ConstantApi
assert(ReflectHelper.getClassAnnotation[Entity2](classOf[Test3Entity]).get.rels(0) == "fieldA")
}
}


Thanks.






Aucun commentaire:

Enregistrer un commentaire