Scala Akka - 接收处理程序中的泛型类型

时间:2014-07-10 19:54:59

标签: scala akka

我试图了解编码此实现的最佳方法。举个例子,这是我的DAO处理程序代码看起来像

trait IDAOHandler[+T]  {
  def create[U <: AnyRef: Manifest](content: U): Try[String]
}

class MongoDAOHAndler extends IDAOHandler[+T]...

所以我创建的actor将处理我的所有持久性任务,包括序列化内容和更新MongoDB数据库。

所以我使用的是akka,技巧是在receive方法中,我如何处理泛型类型参数。即使我的actor代码是非泛型的,但它将要接收的消息将是泛型类型,并且基于createDAO中的内容类型,我计划获得适当的DAO处理程序(描述为aboe)并调用该方法。

case class createDAO[T](content: T) (implicit val metaInfo:TypeTag[T])

class CDAOActor(daofactory: DAOFactory) extends BaseActor {
  def wrappedReceive = {
    case x: createDAO[_] => pmatch(x)
  }

  def pmatch[A](c: createDAO[A]) {
     //getting dao handler which will not work because it needs manifest
  }
}

如果有任何其他方法可以重新编写此实现,请告诉我。

2 个答案:

答案 0 :(得分:3)

您可能已经知道这一点,但有一点背景只是为了确定:在Scala(和Java)中我们有所谓的类型擦除,这意味着参数类型用于在编译期间验证代码的正确性但随后被删除(并且“不给运行时成本”,http://docs.oracle.com/javase/tutorial/java/generics/erasure.html)。模式匹配在运行时发生,因此参数类型已被擦除。

好消息是,您可以使用TypeTag像您在案例类中所做的那样使用Scala编译器保留已擦除的类型,或ClassTag包含较少的信息但保留已擦除的类型。您可以从方法.erasure(Scala 2.11中的.runtimeClass)获取已擦除的类型,该方法将返回T类型的Java类。您仍然无法将其用作方法调用的类型参数,因为它再次发生在编译时,您现在在运行时查看该类型,但您可以做的是在运行时将此类型与if / else或模式匹配。

例如,您可以在您的daofactory上实现一个方法,该方法接受Class[_]参数并返回该类的DAO实例。在pmatch中,您将从标记中取出已擦除的类型并传递给它。

以下是有关标签的更多信息,它们存在的原因以及它们的工作原理: http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html

答案 1 :(得分:0)

我采用了一种不同的方法,一种调度程序模式,所以这里是修改后的代码

trait IDAOProcess 
{
  def process(daofactory:IDAOFactory,sender:ActorRef) 
}

case class createDAO[T <: AnyRef : Manifest](content:T) (implicit val metaInfo:TypeTag[T]) extends IDAOProcess
{
  def process(daofactory:IDAOFactory,sender:ActorRef)
  {
    for ( handler <- daofactory.getDAO[T] ) 
    {
      handler.create(content)
    }
  }
}

class DAOActor(daofactory:IDAOFactory) extends BaseActor  
{
  def wrappedReceive =
  {
    case x:IDAOProcess => 
      {
        x.process(daofactory,sender)
      }
  }
}