Scala Playframework插件和泛型

Scala Playframework插件和泛型,scala,generics,playframework,scala-2.10,Scala,Generics,Playframework,Scala 2.10,我想实现这样一种情况:带有泛型参数的抽象类和实现该类的具体插件 例如: abstract class BasePlugin[T] extends Plugin { def d: T } class MyPlugin(app: Application) extends BasePlugin[String] { val d = "test" } 我的愿望是实现以下目标: val plugin = app.plugin[BasePlugin[String]] //Ok, plugin =

我想实现这样一种情况:带有泛型参数的抽象类和实现该类的具体插件

例如:

abstract class BasePlugin[T] extends Plugin {
  def d: T
}

class MyPlugin(app: Application) extends BasePlugin[String] {
  val d = "test" 
}
我的愿望是实现以下目标:

val plugin = app.plugin[BasePlugin[String]]
//Ok, plugin = Some(MyPlugin)

val plugin = app.plugin[BasePlugin[Int]]
//KO, plugin = None
当然这不会发生,因为myPlugin使用任何类型作为参数(类型擦除?)。
无论如何,找到一种技术来获得上述信息对我来说是非常有效的。有什么想法吗?

play plugin api在查找属于Java一部分的插件时使用Class.isAssignableFrom,因此Scala获得ClassTag/TypeTags不会有帮助

也许您可以创建自己的子插件格式,例如:

trait SubPlugin[T] {
  def doSomething(t: T) {}
}

trait MetaPlugin {

  private val subPlugins: Seq[(Class[_], SubPlugin[_])] = ???

  def subPlugin[T](implicit classTag: ClassTag[T]): Option[SubPlugin[T]] = {
    subPlugins.collectFirst {
      case (c, p) if c.isAssignableFrom(classTag.runtimeClass) => p.asInstanceOf[SubPlugin[T]]
    }
  }
}

object MetaPlugin {

  def apply[T](implicit app: play.api.Application, classTag: ClassTag[T]): Option[SubPlugin[T]] =
    app.plugin[MetaPlugin].flatMap(_.subPlugin[T])

}


object AndThenSomeWhere {
  import play.api.Play.current
  MetaPlugin[String].map(_.doSomething("a string"))
}

Scala有一种称为ClassTag的东西,它使得即使应用程序已经编译,也可以保留类型信息。它在scala 2.10之前被称为Manifest。也许你可以用它们来解决这个问题?!