2013-05-08 13 views
7

Zaimplementowałem kod wspomniany w Get companion object instance with new Scala reflection API (kod stąd: https://gist.github.com/xeno-by/4985929).Pobierz instancję obiektu towarzyszącego modułu wewnętrznego za pomocą interfejsu API do refleksji Scala

Działa to dobrze dla każdej standardowej klasy klas przypadków. Niestety w niektórych klasach projektu otrzymuję wyjątek: scala.ScalaReflectionException: object Tensor is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror Wyjątkiem jest całkiem jasne, więc starałem się zmienić swój kod w następujący sposób:

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

Ale teraz dostaję scala.ScalaReflectionException: expected a member of class Tensor, you provided object Prototype2.SPL.SPL_Exp.Tensor a ja nie dowiedzieć się, jak zmień kod, aby to naprawić. Każda pomoc jest bardzo cenna!

Aktualizacja: I dostarczyć niektóre kodu dla lepszej powtarzalności:

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

To pytanie http://stackoverflow.com/questions/11084408/scala-reflection-error-this-is-an-inner-module-use-reflectmodule-on-an-instanc może być związane – leo

Odpowiedz

3

należy mieć instancję modułu. Możesz uzyskać lustro dla symbolu Tensor tylko z lustra 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 

Można dostać wystąpienie Spl używając trochę brzydkie Magic:

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

nie należy robić tak, dopóki można.

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

Thanks dużo! Niestety mam (w ogólnym przypadku) odniesienie do SPL nie pod ręką. Odpowiednio, parametr caseclassinstance (który może nie być wewnętrzną klasą SPL) musi wystarczyć w moim przypadku, aby uzyskać obiekt towarzyszący. – leo

+0

Nie można tego osiągnąć bez lustra, na przykład 'SPL'. – senia

+0

@leo: Zaktualizowałem swoją odpowiedź. – senia

Powiązane problemy