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

Generic mapping function to handle enumeration types

我有以下枚举类型。

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)。

这是 slick 的非工作版本 table:

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 信息并创建一个 运行 实例来调用 returns 枚举 Value 的应用方法。我必须将 .asinstanceOf[V] 添加到 apply 方法的结果中,否则会出现关于 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)