0

我想获得一个类型的名称,作为一个字符串,没有运行时反射。

使用宏,并使用类型的实例,我可以这样做:

def typeNameFromInstance[A](instance: A): String = 
  macro typeNameFromInstanceImplementation[A]

def typeNameFromInstanceImplementation[A](
  c: Context)(
    instance: c.Expr[A]): c.Expr[String] = {
  import c.universe._

  val name = instance.actualType.toString
  c.Expr[String](Literal(Constant(name)))
}

如果没有该类型的实例,我该如何做到这一点?我想要一个函数签名,如:

def typeName[A]: String

我不能使用 ClassTags,因为它们不提供完整的类型名称,只提供已擦除的类型。由于线程安全问题,我显然也不能使用 TypeTags 。

编辑:看起来这是不可能的(例如嵌套函数调用)。下面接受的答案在评论中说明了这一点。

4

1 回答 1

1

您可以访问代表宏应用程序的树:c.macroApplication

def typeName[T]: String = macro typeName_impl[T]

def typeName_impl[T](c: Context): c.Expr[String] = {
  import c.universe._

  val TypeApply(_, List(typeTree)) = c.macroApplication
  c.literal(typeTree.toString())
}

编辑:

另一种获得相同效果的方法,但可能更好一点:

def typeName[T]: String = macro typeName_impl[T]

def typeName_impl[T: c.WeakTypeTag](c: Context): c.Expr[String] = {
  import c.universe._

  c.literal(weakTypeOf[T].toString())
}
于 2013-03-27T00:22:02.367 回答