使用相同的方法生成派生特征,但在 Scala 的每个方法中没有第一个参数

问题描述

上下文

我在我的 Scala 后端应用程序中定义了一些“客户端”接口,它们大致具有以下形状:

trait BackendClient {
  def foo: FooClient
}
trait FooClient {
  def doSomething(authToken: AuthNToken,request: MyBarRequest): Future[Unit]
  def getSomething(authToken: AuthNToken,id: MyId): Future[MyResource]
}

我想在后端的方法签名中保留 authToken 以提醒实现他们应该检查每个方法调用的身份验证。

不过在前端,到处传递相同的令牌会很烦人,所以理想情况下我想要一个“经过身份验证的”客户端:

// Would like to auto-generate this given `FooClient`
trait AuthenticatedFooClient {
  def doSomething(request: MyBarRequest): Future[Unit]
  def getSomething(id: MyId): Future[MyResource]
}

// Auto-generating this too would be nice but not as important
class AuthenticatedFooClientImpl(authToken: AuthNToken,delegate: FooClient) extends AuthenticatedFooClient {
  override def doSomething(request: MyBarRequest): Future[Unit] = delegate.doSomething(authToken,request)
  override def getSomething(id: MyId): Future[MyResource] = delegate.getSoemthing(authToken,id)
}

这样我就可以在前端有这样的东西:

trait AuthenticatedBackendClient {
  def foo: AuthenticatedFooClient
}
class FrontendAuthServiceImpl(backendClient: BackendClient) extends FrontendAuthService {
  private val getTokenOrAuthenticate: Task[AuthNToken] = Task { ... }.memoizeOnSuccess

  val backendClient: Task[AuthenticatedBackendClient] = for {
    authToken <- getTokenOrAuthenticate
    authenticatedFoo = new AuthenticatedFooClientImpl(authToken,backendClient.foo)
  } yield new AuthenticatedBackendClient {
      override def foo: AuthenticatedFooClient = authenticatedFoo
    }
}
...
...
...
val someId: MyId = ...
val myResource: Task[MyResource] = for {
  backendClient <- frontendAuthService.backendClient
  myResource <- Task.fromFuture(backendClient.foo.getSomething(someId))
} yield myResource

问题

我不想手动维护我的客户端特征的 2 个副本,一个在方法中带有 auth 令牌,一个没有。

我很确定我可以编写自己的注释处理器(我知道宏在 Scala 中可能更惯用,但我从来没有真正开始学习它们)来生成我想要的代码,但这感觉就像是什么这应该可以用现有的库/工具解决。

具体来说,我感觉我应该能够生成一个与另一个 trait 相同的 trait,但会删除所有其他 trait 方法的第一个参数。

有什么想法吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)