Scala反射:给定一个getter符号,找到相应的setter符号的最简单方法是什么?

时间:2014-02-28 20:31:46

标签: scala reflection deep-copy

简短版本: 给定一个getter符号我想找到相应的setter符号。

长版:

下面是Scala Reflection的一个小实用程序类。

我计划使用这个类深层复制Hibernate Entities(抽象类UUIDEntity的子类)。

我将深拷贝分成两部分,1)对象图中的每个对象进行值复制2)连接隔离的拷贝以形成克隆的对象图。这个问题只涉及第一部分。

root成为实体。

首先,我想创建root的值副本,让我们称之为copy。值复制意味着我只填写副本中的值字段(请参阅下面的值字段的定义)。

这应该在getValueCopy方法中进行。

有val copy,但在使用val copy= constructorMirror.apply()

创建后,其字段仍为空

所以我需要将root中的字段复制到copy。为此,我需要获取字段的setter和getter(更准确地说,值字段是引用值类,如Int,String,Long等的字段)。

到目前为止,我设法找到了值字段的getter(valueGetters),但是,我的问题是我想找到相应的setter。但我真的不知道什么是将安装者与吸气剂配对的最佳方式?

使用方法名称是唯一的方法吗?这就是我天真的做法,但我的感觉告诉我必须有更好的方法。

欢迎任何建议。谢谢你的阅读。

import scala.reflect.runtime.universe._
import java.util
import model.UUIDEntity
import scala.collection.JavaConversions._
import scala.collection.mutable


case class ReflectionOfEntity(root:AnyRef) {
 // require(root.isInstanceOf[UUIDEntity[_]])  
  val rtmMirror                   =runtimeMirror(getClass.getClassLoader)
  val instanceMirror : InstanceMirror =rtmMirror.reflect(root)
  val classSymbol    : ClassSymbol    =rtmMirror.reflect(root).symbol
  val classMirror    : ClassMirror    =rtmMirror.reflectClass(classSymbol)

  val theType        : Type           =rtmMirror.reflect(root).symbol.toType


  val methods        : Iterable[MethodSymbol]=
    theType.declarations.filter(_.isMethod).map(_.asMethod)

  val constructorSymbol:MethodSymbol=methods.filter{m=>m.isConstructor && m.paramss.flatten.
    isEmpty}.headOption.
    getOrElse(throw new RuntimeException("no parameterless constructor in root!") )

  val constructorMirror: MethodMirror = classMirror.reflectConstructor(constructorSymbol)


  val valueGetters:Iterable[Symbol]=theType.members.filter{
    case ms:MethodSymbol=>ms.isGetter && isValueType(ms.returnType)
    case _ => false
  }

  def isValueType(tpe:Type)=
    List(typeOf[String],typeOf[AnyVal],typeOf[java.lang.Long]).exists{tpe <:< _}

  def getValueCopy= {
    val copy= constructorMirror.apply()
    val copyR=ReflectionOfEntity(copy)
    //valueGetters.foreach()
    copy
  }
}

1 个答案:

答案 0 :(得分:1)

MethodSymbol为字段提供isCaseAccessorisGetterisSetteraccessed,为设置者提供setter

如果需要代码,我可以使用这种做法,但可能不是。

我是否在寻找与您不同的ScalaDoc?有时候很难知道在哪里看。

编辑:实际上它位于TermSymbolApi

更新

scala> class C(var i: Int, var s: String)
defined class C

scala> typeOf[C].declarations.filter(s => s.isMethod && s.asMethod.isGetter && s.asMethod.setter != NoSymbol)
res10: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(method i, method s)

scala> .map { s => val m = s.asMethod ; (m, m.setter) }
res11: Iterable[(reflect.runtime.universe.MethodSymbol, reflect.runtime.universe.Symbol)] = List((method i,method i_=), (method s,method s_=))