11

感谢我之前问题的答案,我能够创建一个函数宏,以便它返回一个Map将每个字段名称映射到其类的值,例如

...

trait Model

case class User (name: String, age: Int, posts: List[String]) extends Model {
  val numPosts: Int = posts.length

  ...

  def foo = "bar"

  ...
}

所以这个命令

val myUser = User("Foo", 25, List("Lorem", "Ipsum"))

myUser.asMap

返回

Map("name" -> "Foo", "age" -> 25, "posts" -> List("Lorem", "Ipsum"), "numPosts" -> 2)

这是生成Tuples 的地方Map(参见 Travis Brown 的回答):

...

val pairs = weakTypeOf[T].declarations.collect {
  case m: MethodSymbol if m.isAccessor =>
    val name = c.literal(m.name.decoded)
    val value = c.Expr(Select(model, m.name))
    reify(name.splice -> value.splice).tree
}

...

现在我想忽略有@transient注释的字段。如何检查方法是否有@transient注释?

我正在考虑将上面的代码段修改为

val pairs = weakTypeOf[T].declarations.collect {
   case m: MethodSymbol if m.isAccessor && !m.annotations.exists(???) =>
      val name = c.literal(m.name.decoded)
      val value = c.Expr(Select(model, m.name))
      reify(name.splice -> value.splice).tree
}

但我找不到我需要写的exists部分内容。我将如何获得@transientAnnotation以便我可以在那里通过它?

提前致谢!

4

1 回答 1

11

注释将在其val自身上,而不是在访问器上。访问 的最简单方法val是通过accessedon 方法MethodSymbol

def isTransient(m: MethodSymbol) = m.accessed.annotations.exists(
  _.tpe =:= typeOf[scala.transient]
)

现在你可以在你的collect:

case m: MethodSymbol if m.isAccessor && !isTransient(m) =>

请注意,isTransient我在此处给出的版本必须在您的宏中定义,因为它需要导入 from ,但如果您在多个宏中执行此类操作,则c.universe可以通过添加参数将其排除。Universe

于 2013-06-21T13:58:34.457 回答