用于处理枚举类型的泛型映射函数



我有以下枚举类型。

class Payment extends Enumeration {
  type Payment = Value
  val Cash, CreditCard, Unspecified = Value
}
object Payment extends Payment
class Ticket extends Enumeration {
  type Ticket = Value
  val Normal, Discount, Other = Value
}
object Ticket extends Ticket

我将枚举声明为类而不是对象,因为我稍后将需要类型信息(对于 MappedColumnType)。

这是光滑表的非工作版本:

class Stats(tag: Tag) extends Table[Stat](tag, "STATS") {
  implicit def enumToInt[E <: Enumeration : ClassTag, V : ClassTag](implicit conv: V => E#Value): BaseColumnType[V] =
    MappedColumnType.base[V, Int] (
      value => value.id,
      num => implicitly[ClassTag[E]].runtimeClass.newInstance().asInstanceOf[E](num).asInstanceOf[V]
    )
  def entityid = column[Int]("ENTITYID")
  def email = column[String]("EMAIL")
  def payment = column[Payment]("PAYMENT")
  def ticket = column[Ticket]("TICKET")
  def phone = column[String]("PHONE")
  def ticket_source = column[TicketSource]("TICKETSOURCE")
  def * = (entityid, email, payment, ticket, phone, ticket_source) <>
    (Stat.tupled, Stat.unapply)
}

我的目标是定义一个通用映射器函数来处理所有枚举,因为转换方法对所有类型的枚举(值到 id、id 到值)都有效。

在映射器函数中,我尝试捕获 ClassTag 信息并创建一个正在运行的实例来调用返回枚举Value的 apply 方法。 我不得不apply方法的结果中添加.asinstanceOf[V],否则错误会增加E#ValueV的期望值不匹配。现在,这是我得到的错误消息:

Tables.scala:45: could not find implicit value for parameter tm: scala.slick.ast.TypedType[com.yokyer.tiyatrosever.models.Payment]
[error]   def payment = column[Payment]("PAYMENT")
[error]                                ^
Tables.scala:46: could not find implicit value for parameter tm: scala.slick.ast.TypedType[com.yokyer.tiyatrosever.models.Ticket]
[error]   def ticket = column[Ticket]("TICKET")

我是 scala 的新手,我把一堆关于反射的食谱放在一起,想知道我是否做错了什么根本上的事情。

你需要

创建一个MappedColumnType

import profile.simple._
def enumValueMapper(enum: Enumeration) = MappedColumnType.base[enum.Value, String](
    e => e.toString,
    s => Try(enum.withName(s)).getOrElse(throw new IllegalArgumentException
                                        (s"enumeration $s doesn't exist $enum 
                                        [${enum.values.mkString(",")}]"))
)
def enumIdMapper(enum: Enumeration) = MappedColumnType.base[enum.Value, Int](
    e => e.id,
    i => enum.apply(i)
)

然后你可以使用

// It convert Enum to Int
implicit val paymentMapper = enumIdMapper(Payment) 

// It convert Enum to String
implicit val paymentMapper = enumValueMapper(Payment) 

最新更新