1

ケースクラスのコンストラクターフィールドを深く歩くコードがありますが、もちろんそれ自体が複雑な場合があります (モノ、マップ、オプション、およびその他のケースクラスのリスト)。実行時にフィールド値を抽出するために見つけたコードは、最高レベルのフィールドではうまく機能しますが、より深いフィールドにアクセスしようとすると爆発します。以下の例。

私の実生活では、アプリケーションが各レベルのフィールドを内省しているので、「もの」が別のケースクラスであることを知っており (シンボル/タイプを持っています)、Dos のフィールドのシンボル/タイプを知っています。でもこれは実行時に取得するので、[T]/Manifest[T]がわからないのでぶっ飛んでいると思います。リフレクションを介して実行時にこれを取得する方法はありますか? コードはどのように変更される可能性がありますか? 私が見つけた例はすべてさまざまなものを必要とするように見えました[T]、「dos」には必要ありませんよね?

case class Uno( name:String, age:Int, pets:List[String], stuff:Dos )
case class Dos( foo:String )

object Boom extends App {
    val ru = scala.reflect.runtime.universe
    val m = ru.runtimeMirror(getClass.getClassLoader)

    val u = Uno("Marcus",19,List("fish","bird"),Dos("wow"))

    println("NAME: "+unpack(u,"name")) // Works
    println("PETS: "+unpack(u,"pets")) // Works

    // ----- Goes Boom -------
    val dos = unpack(u,"stuff")
    println("Other: "+unpack(dos,"foo")) // Boom!
    // -----------------------

    // Get object value for named parameter of target
    def unpack[T]( target:T, name:String )(implicit man:Manifest[T]) : Any = {
        val im = m.reflect(target)
        val fieldX = ru.typeOf[T].declaration(ru.newTermName(name)).asTerm.accessed.asTerm
        im.reflectField(fieldX).get
    }

}
4

1 に答える 1

3

あなたはまさにその通りです。あなたのタイプはdosですAny

FieldMirror.symbol.typeSignature は、typeOf[Dos] から得られるものです。

したがって、unpack からペア (Any、Type) を返して、unpack (ターゲット、タイプ、名前) に何かを渡すことを検討してください。やや好き:

case class Uno(name: String, age: Int, pets: List[String], stuff: Dos)
case class Dos(foo: String)

object Boom extends App {
  import scala.reflect.runtime.universe._
  import scala.reflect.runtime.{ currentMirror => cm }
  import scala.reflect.ClassTag

  val u = Uno("Marcus", 19, List("fish", "bird"), Dos("wow"))

  println("NAME: " + unpack(u, "name")) // Works
  println("PETS: " + unpack(u, "pets")) // Works

  // ----- Goes Boom -------
  val (dos, dosT) = unpack(u, "stuff")
  println("Other: " + unpack(dos, dosT, "foo")) // Boom! ...or fizzle
  // -----------------------

  def unpack[T: TypeTag](target: T, name: String): (Any, Type) = unpack(target, typeOf[T], name)

  // Get object value for named parameter of target
  def unpack[T](target: T, t: Type, name: String): (Any, Type) = {
    val im = cm.reflect(target)(ClassTag(target.getClass))
    val fieldX = t.declaration(newTermName(name)).asTerm.accessed.asTerm
    val fm = im.reflectField(fieldX)
    (fm.get, fm.symbol.typeSignature)
  }
}
于 2013-06-09T05:38:47.340 に答える