【问题标题】:How do I use Scala reflection to get a property from a method annotation如何使用 Scala 反射从方法注释中获取属性
【发布时间】:2017-03-02 18:47:09
【问题描述】:

所以我目前有以下:

import com.wordnik.swagger.annotations.ApiModel
import reflect.runtime.universe._

case class Model(
                  name: String,
                  qualifiedType: String,
                  properties: Map[String, ModelProperty],
                  description: Option[String] = None)

case class ModelProperty(
                          `type`: String,
                          qualifiedType: String,
                          description: Option[String] = None,
                          items: Option[ModelRef] = None)

case class ModelRef(
                     `type`: String,
                     ref: Option[String] = None,
                     qualifiedType: Option[String] = None)


class ModelHelper {

  def apply(models: Seq[Class[_]]) : Seq[Model] = {
    models.map(m =>
      Model(m.getSimpleName, m.getName, null, annotations(m))
    )
  }

  private def annotations(c : Class[_]) : Option[String] =
    c.getAnnotations.toSeq.map {
      case api : ApiModel => api.description
    }.headOption

  private def getType[T](clazz: Class[T]): Type = {
    val r = runtimeMirror(clazz.getClassLoader)
    r.classSymbol(clazz).toType
  }

  private def properties(c : Class[_]) = {
     getType(c).members.view.filter{!_.isMethod}.map { m =>
       m.annotations.map { a =>
         if(a.tree.tpe =:= typeOf[ApiModelProperty]) {
           a.tree.tpe.??? //<--stuck here
         }
       }
     }
  }
}

def annotations() 中,我可以从ApiModel 类注释中获取所有描述字段。在properties,我想从ApiModelProperty抓取字段。

在 SBT 控制台中,如果我向下钻取,我可以清楚地看到我想要的注释:

...
scala> t.members.view.filter{!_.isMethod}map{ m => { m.annotations }}).head.head.tree
q: reflect.runtime.universe.Tree = new com.wordnik.swagger.annotations.ApiModelProperty @scala.annotation.meta.field(value = "A list of errors on the asset in five different containers.")

..但我不确定要匹配什么才能真正获得该特定注释的实例,就像我在上面的annotations() 中所做的那样。我想我真的不需要实例,我只需要得到value。我该怎么做呢?我在 Scala 2.11.8 上。

【问题讨论】:

    标签: scala reflection annotations scala-2.11


    【解决方案1】:

    我最终找到了解决方案。

      private def properties(c: Class[_]): Map[String, ModelProperty] = {
        getType(c).members.view.filter {!_.isMethod}.map { m =>
          m.name.toString -> ModelProperty(
            toUsefulType(m.typeSignature.toString),
            m.typeSignature.toString,
            m.annotations.find { a =>
              a.tree.tpe =:= typeOf[com.wordnik.swagger.annotations.ApiModelProperty] || 
              a.tree.tpe =:= typeOf[io.swagger.annotations.ApiModelProperty] }.flatMap { b =>
                b.tree.children.flatMap { c =>
                  c.collect {
                    case Literal(Constant(value)) => value
                  }
                }.headOption
              }.getOrElse("").toString
          )
        }.toMap
      }
    

    参考资料:

    Veeb's Brain Dump: Reflecting Annotations in Scala 2.10 - 这篇博文使用了一些已弃用的调用,我在对 Scala 2.11 的回答中更新了这些调用

    Accessing an Annotation Value in Scala 的答案/cmets 也证明很有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-21
      • 2011-01-02
      相关资源
      最近更新 更多