ReactiveMongo的BSON宏和泛型问题

时间:2014-02-23 06:50:37

标签: scala generics bson scala-macros reactivemongo

以下代码对我失败:

object Message {
    def parse[T](bsonDoc: BSONDocument): Try[T] = {
        implicit val bsonHandler = Macros.handler[T]
        bsonDoc.seeAsTry[T]
    }
}

Message.parse[messages.ClientHello](data)

错误是:

No apply function found for T
    implicit val bsonHandler = Macros.handler[T]
                                             ^

但是,如果我对一个类型(我的一个案例类)进行硬编码,那很好:

object Message {
    def parse(bsonDoc: BSONDocument): Try[ClientHello] = {
        implicit val bsonHandler = Macros.handler[ClientHello]
        bsonDoc.seeAsTry[ClientHello]
    }
}

Message.parse(data)

所以我认为这是使用泛型的问题。顺便说一下,我必须import messages.ClientHello。如果我只使用messages.ClientHello,我会得到:

not found: value ClientHello
    implicit val bsonHandler = Macros.handler[messages.ClientHello]
                                             ^

我如何实现我正在尝试做的事情,即使用单个方法获取BSON文档并返回相应案例类的实例?

1 个答案:

答案 0 :(得分:2)

1)宏应用程序在遇到时会立即扩展(嗯,模拟一些与此类无关的类型推断的细节)。这意味着当您编写处理程序[T]时,处理程序将尝试使用T作为类型参数进行扩展。这不会导致任何好的,因此错误。要使其工作,您需要将Message.parse转换为宏本身。

2)这是因为ReactiveMongo宏是不卫生的。具体来说,https://github.com/ReactiveMongo/ReactiveMongo/blob/v0.10.0/macros/src/main/scala/macros.scala#L142在像你这样的情况下无法正常工作,因为它使用类的简单名称,而不是完全限定名。我认为使宏正常工作的最佳方法是使用Ident(伴侣),而不是Ident(companion.name) - 这将确保此标识符绑定到伴侣,而不是具有相同名称的范围内的东西。