在宏中查找实际类型

时间:2015-12-17 06:02:09

标签: scala scala-macros

我正在尝试编写一个提取类型信息的宏。这是一个最小化的版本。

class Extractor[E] {
  def extract(entity: E): Unit = macro ExtractorImpl.extractImpl[E]
}

object ExtractorImpl {
  def extractImpl[E: c.WeakTypeTag](c: Context)(entity: c.Expr[E]): c.Tree = {
    import c.universe._

    val actualType = implicitly[WeakTypeTag[E]].tpe
    c.info(c.enclosingPosition, actualType.toString, true)

    q"{}"
  }
}

以下是Extractor的典型实现:

case class Person(name: String)
object PersonExtractor extends Extractor[Person]

如果我在PersonExtractor.extract(new Person("test name"))中直接使用此类,则会将Person打印为信息。但是,如果我间接使用它,如下所示,它只打印E

class Mapper[E](extractor: Extractor[E]) {
  def extract(e: E) = extractor.extract(e)
}

class PersonMapper extends Mapper[Person](new Extractor[Person])

class Test {
  new PersonMapper().extract(new Person("test name"))
}

如何将Person类型设为actualType

1 个答案:

答案 0 :(得分:1)

使用隐式宏

trait Extractor[E] {
  def extract(entity: E): Unit
}

object Extractor {
  implicit def i[E] : Extractor[E] = macro ExtractorImpl.extractImpl[E]
}

object ExtractorImpl {
  def extractImpl[E: c.WeakTypeTag](c: Context):c.Tree = {
    import c.universe._

    val actualType = c.weakTypeOf[E]
    c.info(c.enclosingPosition, actualType.toString, false)

      q"""
        new Extractor[$actualType]{
          def extract(entity: $actualType): Unit = println("hello world")
        }
      """
  }
}

// test

case class Person(name: String)

//object PersonExtractor extends Extractor[Person]

class Mapper[E] {
  def extract(e: E)(implicit extractor: Extractor[E]) = extractor.extract(e)
}

class PersonMapper extends Mapper[Person]

class Test {
  new PersonMapper().extract(new Person("test name")) // show info:Person 
}

编辑: // test2

class Mapper2[E](extractor: Extractor[E]) {
  def extract(e: E) = extractor.extract(e)
}

object Mapper2 extends Mapper2[Person](Extractor.i[Person])//also  show info:Person