final class ContactInfo extends StaticAnnotation{}
case class Person(val id: String,
val firstName: String,
val lastName: String,
@ContactInfo val phoneNumbers: Seq[String],
@ContactInfo val email: String)
def getContactInfoFields[T: TypeTag]: Seq[String] = {
???
}
预期输出getContactInfoFields [Person] =(“phoneNumbers”,“email”)
Riffing off the answer to a similar question on SO我试过了
def getContactInfoFields[T: TypeTag]: Seq[String] = {
val fields = typeOf[T].members.collect{ case s: TermSymbol => s }.
filter(s => s.isVal || s.isVar)
fields.filter(_.annotations.exists(_.isInstanceOf[ContactInfo]))
.map(x=>x.name.toString).toSeq
}
然而在实践中,这将返回一个空序列。我错过了什么?
答案 0 :(得分:1)
您可以在类型级别表示此信息。
sealed trait ContactInfo
case class PhoneNumbers(numbers: Seq[String]) extends ContactInfo
case class Email(email: String) extends ContactInfo
case class Person(id: String, firstName: String, lastName: String, phoneNumbers: PhoneNumbers, email: Email)
def contactInfo[T: TypeTag] = typeOf[T].members.filter(!_.isMethod).map(_.typeSignature).collect {
case t if t <:< typeOf[ContactInfo] => t.typeSymbol.name.toString
}
致电contactInfo[Person]
返回Iterable[String] = List(Email, PhoneNumbers)
答案 1 :(得分:1)
感谢大家的帮助!我设法提出了一个有效的解决方案。事实证明,我试图将JavaUniverse.reflection.Types与Scala Universe反射类型进行比较,这就是过滤器语句失败的原因。以下函数按预期返回
def listContactInfoFields(symbol: TypeSymbol): Seq[String] = {
val terms = symbol.asClass.primaryConstructor.typeSignature.paramLists.head
val annotatedFields = terms.filter(_.annotations.exists(_.tree.tpe =:= typeOf[ContactInfo]))
annotatedFields.map(_.name.toString)
}