Scala 反射更新案例类 val [英] Scala Reflection to update a case class val

查看:36
本文介绍了Scala 反射更新案例类 val的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里使用 scala 和 slick,并且我有一个 baserepository,它负责处理我的类的基本 crud.对于设计决策,我们确实有 updateTime 和 createdTime 列都由应用程序处理,而不是由数据库中的触发器处理.这两个字段都是 joda DataTime 实例.这些字段定义在两个名为 HasUpdatedAt 和 HasCreatedAt 的特征中,用于表

I'm using scala and slick here, and I have a baserepository which is responsible for doing the basic crud of my classes. For a design decision, we do have updatedTime and createdTime columns all handled by the application, and not by triggers in database. Both of this fields are joda DataTime instances. Those fields are defined in two traits called HasUpdatedAt, and HasCreatedAt, for the tables

trait HasCreatedAt {
    val createdAt: Option[DateTime]
}

case class User(name:String,createdAt:Option[DateTime] = None) extends HasCreatedAt

我想知道如何使用反射调用用户复制方法,在数据库插入方法期间更新 createdAt 值.

I would like to know how can I use reflection to call the user copy method, to update the createdAt value during the database insertion method.

在@vptron 和@kevin-wright 评论后编辑

我有一个这样的仓库

trait BaseRepo[ID, R] {

    def insert(r: R)(implicit session: Session): ID
  }

我只想实现一次插入,然后我想在那里更新 createdAt,这就是为什么我不使用 copy 方法,否则我需要在使用 createdAt 列的任何地方实现它.

I want to implement the insert just once, and there I want to createdAt to be updated, that's why I'm not using the copy method, otherwise I need to implement it everywhere I use the createdAt column.

推荐答案

这里回答这个问题是为了帮助其他人解决此类问题.我最终使用此代码使用 Scala 反射来执行我的案例类的复制方法.

This question was answered here to help other with this kind of problem. I end up using this code to execute the copy method of my case classes using scala reflection.

import reflect._
import scala.reflect.runtime.universe._
import scala.reflect.runtime._

class Empty

val mirror = universe.runtimeMirror(getClass.getClassLoader)
// paramName is the parameter that I want to replacte the value
// paramValue is the new parameter value
def updateParam[R : ClassTag](r: R, paramName: String, paramValue: Any): R = {

  val instanceMirror = mirror.reflect(r)
  val decl = instanceMirror.symbol.asType.toType
  val members = decl.members.map(method => transformMethod(method, paramName, paramValue, instanceMirror)).filter {
    case _: Empty => false
    case _ => true
  }.toArray.reverse

  val copyMethod = decl.declaration(newTermName("copy")).asMethod
  val copyMethodInstance = instanceMirror.reflectMethod(copyMethod)

  copyMethodInstance(members: _*).asInstanceOf[R]
}

def transformMethod(method: Symbol, paramName: String, paramValue: Any, instanceMirror: InstanceMirror) = {
  val term = method.asTerm
  if (term.isAccessor) {
    if (term.name.toString == paramName) {
      paramValue
    } else instanceMirror.reflectField(term).get
  } else new Empty
}

有了这个,我可以执行我的案例类的复制方法,替换一个确定的字段值.

With this I can execute the copy method of my case classes, replacing a determined field value.

这篇关于Scala 反射更新案例类 val的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆