簡體   English   中英

如何使用 Scala Guice 綁定使用 monadic 類型參數擴展 Trait 的類?

[英]How to bind a class that extends a Trait with a monadic type parameter using Scala Guice?

我需要綁定這個特性的實現:

trait ClientRepository[F[_]] {
  def list(): F[Iterable[ClientDTO]]
}

到這個實現:

import cats.effect.IO

@Singleton
class ClientRepositoryImpl @Inject()(db: OldDataBase, c: IOContextShift)
    extends ClientRepository[IO] {

  override def list(): IO[Iterable[ClientDTO]] = ???
}

我正在使用 Scala Play! v2.7.2 和 Scala v2.12.8,帶有scala-guice v4.2.1。 為了將特征綁定到它的實現,我想在我的Module.scala做類似的事情:

class Module(environment: Environment, configuration: Configuration)
    extends AbstractModule
    with ScalaModule {

  override def configure() = {

    bind[ClientRepository].to[ClientRepositoryImpl[IO]].in[Singleton]

  }
}

我得到的錯誤是:

[error] app/Module.scala:37:9: kinds of the type arguments (ClientRepository) do not conform to the expected kinds of the type parameters (type T).
[error] ClientRepository's type parameters do not match type T's expected parameters:
[error] trait ClientRepository has one type parameter, but type T has none
[error]     bind[ClientRepository].to[ClientRepositoryImpl[IO]].in[Singleton]
[error]         ^
[error] app/Module.scala:37:31: ClientRepositoryImpl does not take type parameters
[error]     bind[ClientRepository].to[ClientRepositoryImpl[IO]].in[Singleton]
[error]                               ^
[error]

我也試過:

bind[ClientRepository[IO]].to[ClientRepositoryImpl].in[Singleton]

Module.scala:37:9: kinds of the type arguments (cats.effect.IO) do not conform to the expected kinds of the type parameters (type T).
[error] cats.effect.IO's type parameters do not match type T's expected parameters:
[error] class IO has one type parameter, but type T has none
[error]     bind[ClientRepository[IO]].to[ClientRepositoryImpl].in[Singleton]
[error]         ^

bind[ClientRepository[IO[_]]].to[ClientRepositoryImpl].in[Singleton]

Module.scala:37:27: cats.effect.IO[_] takes no type parameters, expected: one
[error]     bind[ClientRepository[IO[_]]].to[ClientRepositoryImpl].in[Singleton]
[error]                           ^

解決這個問題的正確方法是什么?

在閱讀了這個 SO answerthis one之后,我使用 Guice 的TypeLiteral找到了正確的解決方案。

工作解決方案是:

    // In Module.scala configure()
    bind(new TypeLiteral[ClientRepository[IO]] {}).to(classOf[ClientRepositoryImpl])

因為我們必須提供一個可以實例化的類(帶有一個類型參數,在我們的例子中是IO )。 TypeLiteral是一個特殊的類,可讓您指定完整的參數化類型,可用於創建到我們Repo[F[_]]的特定實現的實際綁定。 不能實例化帶有泛型參數的類,但我們可以強制 Guice 選擇一個特定的ClientRepository ,它是用類型參數cats.effect.IO

最后但並非最不重要的是,每當您必須注入特征ClientRepository您還必須指定類型參數。 例如:

class ClientResourceHandler @Inject()(
    routerProvider: Provider[ClientRouter],
    clientRepository: ClientRepository[IO]
)

ClientResourceHandler需要調用 repo,所以我們使用特征ClientRepository[IO] (不僅僅是ClientRepository )注入它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM