2013-05-08 7 views
7

Ho implementato il codice menzionato in Get companion object instance with new Scala reflection API (codice da qui https://gist.github.com/xeno-by/4985929).Ottieni l'istanza dell'oggetto companion di un modulo interno con l'API di riflesso di Scala

Questo funziona perfettamente per qualsiasi classe di classi di casi standard. Purtroppo in alcune classi del progetto ottengo un'eccezione: scala.ScalaReflectionException: object Tensor is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror L'eccezione è abbastanza chiaro, così ho cercato di cambiare il mio codice come segue:

object Reflection { 
    def getCompanionObject(caseclassinstance:Product):Any = { 
     import scala.reflect.runtime.{currentMirror => cm} 
     val classSymbol = cm.classSymbol(caseclassinstance.getClass) 
     val moduleSymbol = classSymbol.companionSymbol.asModule 
     val instanceMirror = cm.reflect(caseclassinstance) 
     val moduleMirror = instanceMirror.reflectModule(moduleSymbol) 
     moduleMirror.instance 
    } 
} 

Ma ora ho un scala.ScalaReflectionException: expected a member of class Tensor, you provided object Prototype2.SPL.SPL_Exp.Tensor e non ho trovato il modo di cambia il codice per risolvere questo problema. Qualsiasi aiuto è molto apprezzato!

Aggiornamento: Ho fornire qualche codice per una migliore riproducibilità:

scala> trait SPL { 
    | case class Tensor() 
    | } 
defined trait SPL 

scala> val s = new SPL {} 
s: SPL = [email protected] 

scala> val t = s.Tensor() 
t: s.Tensor = Tensor() 

scala> object Reflection { /* as in the first code snippet*/} 
defined module Reflection 

scala> Reflection.getCompanionObject(t) 
scala.ScalaReflectionException: object Tensor is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror 
... 

scala> object Reflection { /* as in the second code snippet*/} 
defined module Reflection 

scala> Reflection.getCompanionObject(t) 
scala.ScalaReflectionException: expected a member of class Tensor, you provided object SPL.Tensor 
... 
+0

Questa domanda http://stackoverflow.com/questions/11084408/scala-reflection-error-this-is-an-inner-module-use-reflectmodule-on-an-instanc potrebbe essere correlato – leo

risposta

3

si dovrebbe avere un'istanza del modulo. È possibile ottenere il mirror per il simbolo Tensor solo dal mirror di Spl.

trait Spl { 
    case class Tensor(s: String) 
} 

val spl = new Spl {} 

val t = spl.Tensor("T") 

// mirror for module spl 
val moduleMirror = cm.reflect(spl) 
// class symbol for Tensor 
val instanceSymbol = cm.classSymbol(t.getClass) 
// symbol for companion object 
val companionSymbol = instanceSymbol.companionSymbol.asModule 
// mirror for companion object symbol in spl module mirror 
val companionMirror = moduleMirror.reflectModule(companionSymbol) 

scala> companionMirror.instance 
res0: Any = Tensor 

Si potrebbe ottenere un'istanza di Spl usando un po 'di magia brutto:

val outer = 
    t. 
    getClass. 
    getFields. 
    find(_.getName == """$outer"""). 
    get. 
    get(t) 

Si consiglia di non farlo fino a quando è possibile.

def getCompanionObject(t: Product):Any = { 
    import scala.reflect.runtime.{currentMirror => cm} 
    val outerField = t.getClass.getFields.find(_.getName == """$outer""") 
    val moduleMirror = outerField.map{ _.get(t) }.map{ cm.reflect(_) } 
    val instanceSymbol = cm.classSymbol(t.getClass) 
    val companionSymbol = instanceSymbol.companionSymbol.asModule 
    val companionMirror = 
    moduleMirror. 
     map{ _.reflectModule(companionSymbol) }. 
     getOrElse{ cm.reflectModule(companionSymbol) } 
    companionMirror.instance 
} 
+0

Grazie Un sacco! Purtroppo ho (nel caso generale) il riferimento a SPL non a portata di mano. Rispettivamente il parametro caseclassinstance (che potrebbe non essere una classe interna di SPL) deve essere sufficiente nel mio caso per ottenere l'oggetto companion. – leo

+0

Non è possibile raggiungerlo senza mirror per esempio di 'SPL'. – senia

+0

@leo: ho aggiornato la mia risposta. – senia

Problemi correlati