2017-07-16 46 views
0

[請原諒我長的問題,我仍然在學習斯卡拉]如何正確地綁定一個特點它IMPL當後來有一個隱含參數

我試圖綁定一個通用的特質到其具有隱含參數的泛型impl。清理代碼如下:

trait PersistenceService[T <: SomeOtherClass] { 
    def persist(record: T): Future[Unit] 
} 

class MongoPersistenceService[T <: SomeOtherClass] @Inject()(implicit ec: ExecutionContext, tag: ClassTag[T]) extends PersistenceService[T] { 
    val collectionName: String = tag.runtimeClass.getSimpleName 
    val databaseName = "someDatabase" 

    def db: Future[DefaultDB] = MongoConnectionWrapper.getMongoConnection("mongodb://127.0.0.1", "27017") 
           .flatMap(_.database(databaseName)) 

    def collection: Future[BSONCollection] = db.map(_.collection(collectionName)) 

    def persist(record: T): Future[Unit] = { 
    val result = for { 
     col <- collection 
     writeResult <- col.insert(record) 
    } yield writeResult 
    result.recoverWith { 
         case WriteResult.Code(11000) => throw RecordAlreadyExistsException(record, 
                          "") 
         }.map(_ =>()) 
    } 

    def read(id: BSONObjectID): Future[T] = { 
    val query = BSONDocument("_id" -> id) 
    val readResult: Future[T] = for { 
     coll <- collection 
     record <- coll.find(query).requireOne[T] 
    } yield record 

    readResult.recoverWith { 
          case NoSuchResultException => throw RecordNotFoundException(id) 
          } 
    } 
} 

我正在使用Play,ReactiveMongo和ScalaGuice(所有最新版本)。因此,這裏是我的主模塊類綁定的一切:

class Module(env: Environment, config: Configuration) extends AbstractModule with ScalaModule { 
    def configure(): Unit = { 
    bind[PersistenceService[_]].to[MongoPersistenceService[_]] // Also tried with specific class instead of _ but not working either 
    } 
} 

而且讓我們說我有這樣的PersistenceService我的依賴控制器的一個:

class PersistenceServiceController @Inject()(val PersistenceService: PersistenceService[Bar], cc ControllerComponents) extends AbstractController(cc) { ... } 

和模型(如你可能已經猜到)與其implicits讀/寫:

case class Bar() extends SomeOtherClass() {} 
object Bar { 
    implicit object BarReader extends BSONDocumentReader[Bar] { 
    def read(doc: BSONDocument): Bar = { ... } 
    } 
    implicit object BarWriter extends BSONDocumentWriter[Bar] { 
    def write(bar: Bar): BSONDocument = { ... } 
    } 
} 

有了這些東西,我得到以下運行時異常:

com.google.inject.CreationException: Unable to create injector, see the following errors: 
1) No implementation for reactivemongo.bson.BSONDocumentReader<Bar> was bound. 
    while locating reactivemongo.bson.BSONDocumentReader<Bar> 
    for the 2nd parameter of MongoPersistenceService.<init>(MongoPersistenceService.scala:15) 
    at Module.configure(Module.scala:14) (via modules: com.google.inject.util.Modules$OverrideModule -> Module) 
2) No implementation for reactivemongo.bson.BSONDocumentWriter<Bar> was bound. 
    while locating reactivemongo.bson.BSONDocumentWriter<Bar> 
    for the 3rd parameter of persistence.MongoPersistenceService.<init>(MongoPersistenceService.scala:15) 
    at Module.configure(Module.scala:14) (via modules: com.google.inject.util.Modules$OverrideModule -> Module) 
3) No implementation for scala.reflect.ClassTag<Bar> was bound. 
    while locating scala.reflect.ClassTag<Bar> 
    for the 5th parameter of MongoPersistenceService.<init>(MongoPersistenceService.scala:15) 
    at Module.configure(Module.scala:14) (via modules: com.google.inject.util.Modules$OverrideModule -> Module) 

很明顯,我的類MongoPersistenceService應該在執行上下文中得到的東西缺少一些方法。我明白,當您使用guice正確設置您的東西時,Play有點神奇地提供了執行上下文。但在這種情況下,看起來不起作用。

我該如何解決這個問題?

回答

0

嗯,我對這一個感覺不好,但錯誤信息是非常明顯的找到問題。爲了解決這個問題,我不得不手動綁定一個impl爲BSONDocumentReader[Bar],BSONDocumentWriter[Bar]ClassTag[Bar]

我自重構我的代碼更簡單。 但想讓其他人知道問題是什麼。

相關問題