配置映射

时间:2016-04-10 08:48:24

标签: scala playframework playframework-2.0

我有一个基于play框架的Web应用程序。

我的一个端点提供由不同类的输出组成的响应。消费者可以选择他想要在响应中输出哪些输出: GET /model/:modelId?fields=length,width,age。 因此,我有LengthProviderWidthProvider。 现在,我想在控制器中有一个配置图,比如

val providers = Map(
    "length" -> LengthProvider,
    "width"  -> WidthProvider
)

能够通过此地图过滤消费者的输入并应用所有提供者,例如

fields.collect {
    case field if providers.contains(field) => providers(field)(db).get(modelId)
  }

当我尝试构建相应的类时出现问题。 我有一个抽象的FieldProvider

abstract class FieldProvider(db: DB) {
  def get(modelId: Long): Future[Seq[Writes]]
}

相应的实施(LengthProviderWidthProvider)。现在,为了使配置Map编译,我需要为我想要引用的类定义伴随对象(例如,我需要LengthProvider对象)。然后,当我使用Map(类名)的值时,我不能像通常那样初始化类实例,我只能访问随附对象中定义的apply方法。但问题是这不是我定义的抽象类的一部分,因此编译器不理解apply方法签名(因为它只在子类的伴随对象中定义,而不是在父抽象类中定义) :

fields.collect {
    case field if providers.contains(field) => providers(field)(db).get(modelId)
                                                                ↑ won't compile
  }

有没有办法让伴侣对象的apply签名成为抽象类的一部分?还是有另一种更好的方法吗?

1 个答案:

答案 0 :(得分:1)

由于地图中的实例实际上是比较对象,您可以让伴随对象继承自Function1,例如:

object LengthProvider extends ((DB) => LengthProvider) {
  def apply(v1: DB): LengthProvider = new LengthProvider(v1)
}

object WidthProvider extends ((DB) => WidthProvider) {
 def apply(v1: DB): WidthProvider = new WidthProvider(v1)
}

val providers: Map[String, ((DB) => FieldProvider)] = Map(
  "length" -> LengthProvider,
  "width"  -> WidthProvider
)