是否可以通过传入映射中指定的类来调用泛型函数?

时间:2018-12-18 21:15:41

标签: scala reflection playframework generic-type-argument

在这里问,因为我正在拔头发,试图弄清楚我到底需要在这里做什么。

我正在编写一个批处理端点,该端点试图在端点内部执行逻辑之前将请求的主体转换为特定的Scala案例类。

这是我目前所掌握的。首先,我有一个函数executeWithType,它具有通用类型,控制器方法和请求主体,并在将请求主体转换为提供的类型后执行控制器方法。请求参数在此功能之外的范围中可用。

def executeWithType[A](action: () => Action[A], batchRequest: BatchRequest): Future[Result] = {
    action()(request.map(_ => batchRequest.body.map(_.as[A]).get))
}

然后,我有一些代码可根据BatchRequest自身中的内容检查要调用的端点以及要转换的类型。

val res: Future[Result] = (batchRequest.method, batchRequest.endpoint) match {
    case ("POST", "/endpoint1") => {
        executeWithType[EndpointOneType](controller.endpointOne _, batchRequest)
    }
    case ("POST", "/endpoint2") => {
        executeWithType[EndpointTwoType](controller.endpointTwo _, batchRequest)
    }
    case _ => Future.successful(NotFound)
}

上面的方法工作得很好-但是,如果可能的话,我想避免这种与个别情况匹配的元组,而是指定一个Map来代替。在我理想的世界中,紧接其上方的代码块的最终结果将如下所示:

val actions = Map(
    Seq("POST", "/endpoint1") -> (controller.endpointOne _, EndpointOneType),
    Seq("POST", "/endpoint2") -> (controller.endpointTwo _, EndpointTwoType)
)

val res = actions.get(Seq(batchRequest.method, batchRequest.endpoint)) match {
    case Some(action) => {
         executeWithType[action._2](action._1, batchRequest)
    }
    case _ => Future.successful(NotFound)
}

这有可能吗?我一直在努力与之抗争,但我对Scala中反射的理解确实很薄弱,因此我不确定该如何去做。我已经尝试了很多classOf和typeTag以及Class [_]东西,但是我基本上在黑暗中摇摆。希望有人比我更有知识,可以帮助我。

重要的是:

  1. 在Map的值中,元组的第二个空间需要做什么?您如何传递Class变量?
  2. 我们如何使用作为变量的类来调用通用类型的方法?

1 个答案:

答案 0 :(得分:0)

  

我们如何使用作为变量的类来调用通用类型的方法?

不能。但我想提出一个替代解决方案。

只需定义一个本地类而不是元组:

class RequestAction[A](action: () => Action[A]) {
  def apply(request: BatchRequest) = executeWithType(action, request)
}

val actions = Map(
    Seq("POST", "/endpoint1") -> new RequestAction(controller.endpointOne _), // type parameter is inferred
    Seq("POST", "/endpoint2") -> new RequestAction(controller.endpointTwo _)
)

val res = actions.get(Seq(batchRequest.method, batchRequest.endpoint)) match {
    case Some(action) => action(batchRequest)
    case _ => Future.successful(NotFound)
}

(虽然这取决于问题中未显示的代码,但您似乎可以通过传递Action[A]而不是() => Action[A]来简化此操作。)