如何编写通用隐式转换?

时间:2013-08-06 01:01:12

标签: scala generics implicit-conversion spray

你能帮我写一下通用隐式转换吗?

我正在使用Scala 2.10.2和Spray 1.2。

这就是我所拥有的

// for "parameters"
implicit def ObjectIdUnmarshallerString = new Deserializer[String, ObjectId] {
  def apply(value: String) =
    try Right(new ObjectId(value))
    catch {
      case ex: Throwable => Left(MalformedContent(s"Cannot parse: $value", ex))
    }
}

//  for "formParameters"
implicit def ObjectIdUnmarshallerHttpEntity = new Deserializer[HttpEntity, ObjectId] {
  def apply(value: HttpEntity) = ObjectIdUnmarshallerString(value.asString)
}

正如您可以看到HttpEntity的反序列化器 - > ObjectId只使用String-> ObjectId反序列化器。我必须为我在HTTP路由特征中使用的每个类复制粘贴这样的代码。

所以我想如果我可以编写泛型HttpEntity-> T,它将使用范围内可用的Deserializer[String, T]

我试过了:

  implicit def GenericUnmarshallerHttpEntity[T] = new Deserializer[HttpEntity, T] {
    def convertAsString(value: HttpEntity)(implicit conv: Deserializer[String, T]) = conv(value.asString)

    def apply(value: HttpEntity) = convertAsString(value)
  }

可悲的是它不起作用。并说:

could not find implicit value for parameter conv: spray.httpx.unmarshalling.Deserializer[String,T]
    def apply(value: HttpEntity) = convertAsString(value)
                                                  ^

not enough arguments for method convertAsString: (implicit conv: spray.httpx.unmarshalling.Deserializer[String,T])spray.httpx.unmarshalling.Deserialized[T].
Unspecified value parameter conv.
    def apply(value: HttpEntity) = convertAsString(value)
                                                  ^

你能建议怎么做吗?

2 个答案:

答案 0 :(得分:2)

尝试implicit def GenericUnmarshallerHttpEntity[T](implicit conv: Deserializer[String, T]) = ...并从convertAsString删除隐式参数。

正如问题所在,apply并不要求隐含在范围内,因此无法调用convertAsString方法。

答案 1 :(得分:0)

您的apply函数需要隐式传递给convert方法

implicit def GenericUnmarshallerHttpEntity[T] = new Deserializer[HttpEntity, T] {
  def convertAsString(value: HttpEntity)(implicit conv: Deserializer[String, T]) = conv(value.asString)

  def apply(value: HttpEntity)(implicit conv: Deserializer[String, T]) = convertAsString(value)
}