当参数列表相同时,将一个案例类转换为另一个案例类

时间:2015-08-11 18:34:31

标签: scala boilerplate

我有很多类似的案例类,它们意味着不同的东西但具有相同的参数列表。

object User {
  case class Create(userName:String, firstName: String, lastName: String)
  case class Created(userName:String, firstName: String, lastName: String)
}

object Group {
  case class Create(groupName:String, members: Int)
  case class Created(groupName:String, members: Int)
}

鉴于这种设置,我厌倦了编写采用Create类型的参数并返回Created类型的参数的方法。我有大量的测试用例可以完成这类工作。

我可以写一个函数将一个case类转换成另一个。此功能会将User.Create转换为User.Created

def userCreated(create: User.Create) = User.Create.unapply(create).map((User.Created.apply _).tupled).getOrElse(sys.error(s"User creation failed: $create"))

我必须为Group编写另一个这样的函数。 我真正想要的是一个泛型函数,它接受两种类型的case类和一个case类的对象并转换为另一个。像,

def transform[A,B](a: A):B

此外,此功能不应失败减少样板的目的。如果更容易使用,请随意为功能建议不同的签名。

2 个答案:

答案 0 :(得分:10)

无形的救援!

您可以使用Shapeless的X509Certificate2 objCert = new X509Certificate2(); string accountName = "xxxxxstorage"; string accountKey = "qqqqqqqqqqqqqqqjt8DGAI6aBoBzdwwwwwwwwwwwwwzZg=="; StorageCredentials creds = new StorageCredentials(accountName, accountKey); CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true); // Create the blob client. CloudBlobClient blobClient = account.CreateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference("certificate"); CloudBlockBlob blockBlob = container.GetBlockBlobReference("Certificate.p12"); byte[] certData; // Save blob contents to a memorystream. using (var stream = new MemoryStream()) { blockBlob.DownloadToStream(stream); certData = stream.ToArray(); } objCert.Import(certData); 来创建案例类的通用表示,然后可以用它来完成您尝试执行的操作。使用Generic,我们可以强制执行类型和参数名称。

LabelledGeneric

答案 1 :(得分:5)

为了记录,这是我设法实现的最简单的类型安全语法:

implicit class Convert[A, RA](value: A)(implicit ga: Generic.Aux[A, RA]) {
  def convertTo[B, RB](gb: Generic.Aux[B, RB])(implicit ev: RA =:= RB) =
    gb.from(ga.to(value))
}

它可以像这样使用:

case class Create(userName: String, firstName: String, lastName: String)
case class Created(userName: String, firstName: String, lastName: String)

val created = Create("foo", "bar", "baz").convertTo(Generic[Created])

LabelledGeneric同样可以实现更好的类型安全:

implicit class Convert[A, RA](value: A)(implicit ga: LabelledGeneric.Aux[A, RA]) {
  def convertTo[B, RB](gb: LabelledGeneric.Aux[B, RB])(implicit ev: RA =:= RB) =
    gb.from(ga.to(value))
}

val created = Create("foo", "bar", "baz").convertTo(LabelledGeneric[Created]))