感谢my previous question的答案,我能够创建一个函数宏,使其返回一个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)
这是生成Tuple
Map
的地方(见Travis Brown的answer):
...
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
部分找到我需要写的内容。我如何将@transient
作为Annotation
,以便将其传递给那里?
提前致谢!
答案 0 :(得分:11)
注释将在val
本身,而不在访问者身上。访问val
的最简单方法是通过accessed
上的MethodSymbol
方法:
def isTransient(m: MethodSymbol) = m.accessed.annotations.exists(
_.tpe =:= typeOf[scala.transient]
)
现在,您可以在collect
:
case m: MethodSymbol if m.isAccessor && !isTransient(m) =>
请注意,我在此处提供的isTransient
版本必须在您的宏中定义,因为它需要从c.universe
导入,但您可以通过添加{如果您在多个宏中执行此类操作,请参加{1}}论证。