我试图了解编码此实现的最佳方法。举个例子,这是我的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
}
}
如果有任何其他方法可以重新编写此实现,请告诉我。
答案 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)
}
}
}