Можно ли создать провайдера кодеков из общего класса дел? - PullRequest
1 голос
/ 05 июля 2019

Я пытаюсь создать обобщенную функцию, которая выдает CodecProvider из заданного универсального класса case.

В документации макроса BSON нет примеров этого.

Этот (без ответа) вопрос SO похож, но меня это не интересуетв перечислении всех возможных кодеков для данного параметра типа.Кроме того, мой вопрос не касается границ типов или дисперсий типов.

Вот минимальный пример кода, который не компилируется.

import org.mongodb.scala.bson.codecs.Macros

case class Foo(x: Int)

case class Bar[T](x: T)

def fooCodecProvider = Macros.createCodecProvider[Foo]()
// Compiles! (No generic)

def barCodecProvider[T] = Macros.createCodecProvider[Bar[T]]()
// Compile Error:(8, 70) class Bar takes type parameters

Я ожидаю, что barCodecProvider скомпилируетоднако это не так.

Ошибка компиляции, генерируемая вышеприведенным кодом, гласит: class Bar takes type parameters, что сбивает с толку, поскольку я явно предоставил параметр типа T в Bar через сигнатуру универсального barCodecProvider функция.Есть ли у меня ошибка синтаксиса, связанная с типизацией?Является ли ошибка признаком того, что я неправильно использую mongo-scala-driver?

1 Ответ

1 голос
/ 05 июля 2019

Хотя это возможно с другими библиотеками, такими как circe, через неявный поиск. С org.mongodb.scala.bson.codecs.Macros это кажется невозможным, потому что никакая функция Macro не принимает параметры.

Но вы можете сделать это сами, если знаете, как сделать Codec.

Кодек кажется простой чертой с 3 методами encode decode и getEncoderClass

implicit val fooCodec : Codec[Foo] = Macros.createCodecProvider[Foo]()

def barCodecProvider[T: ClassTag](implicit codecT : Codec[T]) = new Codec[Bar[T]] {
  override def decode(reader: BsonReader, decoderContext: DecoderContext): Bar[T] = {
    Bar[T](codecT.decode(reader,decoderContext))
  }

  override def encode(writer: BsonWriter, value: Bar[T], encoderContext: EncoderContext): Unit = {
    codecT.encode(writer,  value.x, encoderContext)
  }
  //the tricky one
  override def getEncoderClass: Class[Bar[T]] = classTag[Bar[T]].runtimeClass.asInstanceOf[Class[Bar[T]]]
}

val barFooCodec : Codec[Bar[Foo]] = barCodecProvider[Foo]

Это простой пример, но он дает представление о том, что вы можете сделать. Используйте макрос для генерации простых экземпляров и составьте эти экземпляры вместе с функциями, используя имплициты для автоматической выборки нужных экземпляров.

...