问题描述
我实现了获取伴随对象实例中提到的代码新的 Scala 反射 API(来自此处的代码 https://gist.github.com/xeno-by/4985929).
I implemented the code mentioned in Get companion object instance with new Scala reflection API (code from here https://gist.github.com/xeno-by/4985929).
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 moduleMirror = cm.reflectModule(moduleSymbol)
moduleMirror.instance
}
}
这适用于任何标准类的案例类.不幸的是,在项目的某些类中,我得到了一个异常:scala.ScalaReflectionException: object Tensor is an internal module, use reflectModule on an InstanceMirror 来获取它的 ModuleMirror
异常很清楚,所以我试图改变我的代码如下:
This works fine for any standard class of case classes. Unfortunately in some classes of the project I get an Exception: scala.ScalaReflectionException: object Tensor is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror
The exception is pretty clear, so I tried to change my code as follows:
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
}
}
但现在我得到一个 scala.ScalaReflectionException: expected a member of class Tensor, you provide object Prototype2.SPL.SPL_Exp.Tensor
我没有找到如何更改代码来解决这个问题.非常感谢任何帮助!
But now I get a scala.ScalaReflectionException: expected a member of class Tensor, you provided object Prototype2.SPL.SPL_Exp.Tensor
and I did not find out how to change the code to fix this. Any help is greatly appreciated!
更新:我提供了一些代码以提高重现性:
Update: I provide some code for better reproducibility:
scala> trait SPL {
| case class Tensor()
| }
defined trait SPL
scala> val s = new SPL {}
s: SPL = $anon$1@165f5a4
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
...
推荐答案
你应该有一个模块的实例.您只能从 Spl
的镜像中获取 Tensor
符号的镜像.
You should have an instance of module. You can get mirror for Tensor
symbol only from mirror of 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
你可以使用一些丑陋的魔法获得一个 Spl
的实例:
You could get an instance of Spl
using a bit of ugly magic:
val outer =
t.
getClass.
getFields.
find(_.getName == """$outer""").
get.
get(t)
在可以之前不要这样做.
You should not do so until you can.
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
}
这篇关于使用 Scala 反射 API 获取内部模块的伴随对象实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!