2017-03-02 69 views
0

所以我現在有獲取屬性如下:如何使用Scala的反射從方法的註釋

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上。

回答

0

我最終找出解決方案。

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 - 本博客文章使用了,我在我的答案更新的斯卡拉2.11

的答案/爲Accessing an Annotation Value in Scala評論也證明了有益的一些過時的電話。