【问题标题】:Scala Reflection : Given a getter Symbol, what is the easiest way to find the corresponding setter Symbol?Scala反射:给定一个getter Symbol,找到相应的setter Symbol最简单的方法是什么?
【发布时间】:2014-02-28 20:31:46
【问题描述】:

短版: 给定一个 getter Symbol 我想找到相应的 setter Symbol。

长版:

下面是 Scala 反射的一个小工具类。

我打算用这个类来深拷贝Hibernate Entities(抽象类UUIDEntity的子类)。

我将深拷贝分为两部分,1)对对象图中的每个对象进行值拷贝 2)将孤立的副本连接起来形成一个克隆的对象图。这个问题只涉及第一部分。

root 成为一个实体。

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

这应该发生在getValueCopy 方法中。

存在 val copy,但在使用 val copy= constructorMirror.apply() 创建后其字段仍为空

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

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

使用方法名是唯一的方法吗?那是我天真地做的事,但我的感觉告诉我,一定有更好的方法。

欢迎提出任何建议。感谢阅读。

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
  }
}

【问题讨论】:

    标签: scala reflection deep-copy


    【解决方案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_=))
    

    【讨论】:

    • 是的,我了解如何获取 getter 或 setter,但问题是找到 getter-setter pairs。换句话说,对于每个 getter,我都想知道它对应的 setter。
    • 从getter来看,accessed.setter就是setter,对吧?我只看了文档,并没有用手指刷新我的记忆。
    • 谢谢,我会试试看,阅读 ScalaDoc 我自己不会想到这一点。
    • ScalaDoc 表示访问器:访问器方法的支持字段,所有其他术语符号的 NoSymbol。现在,什么是支持字段?是正在访问的字段吗?
    • 并将s.asMethod.setter != NoSymbol添加到过滤器以确保有一个setter。
    猜你喜欢
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 2011-04-10
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    相关资源
    最近更新 更多