使用 Scala 的运行时反射查找对象 [英] Finding objects using scala's runtime reflection

查看:42
本文介绍了使用 Scala 的运行时反射查找对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前使用 Scala 2.11.6,将来可能使用 2.11.7.鉴于类路径中已编译的类文件,我想做两件事:

I use scala 2.11.6 currently, possibly 2.11.7 in the future. Given compiled class files in the classpath, I want to do 2 things:

  • 查找实现某个接口的任何对象的名称:

  • Find the name of any objects that implements a certain interface:

trait Service
trait ServiceFactory {
  def create(): Service
}
...
package my.package
object MyServiceFactory extends ServiceFactory {
  def create(): Service = new Service()
}

这里的名称类似于 my.package.MyServiceFactory,因为它实现了 ServiceFactory trait.

Here the name would be something like my.package.MyServiceFactory as it implements the ServiceFactory trait.

给定对象的完全限定名称,我想获取对对象实例的引用.

Given the fully qualified name of the object I want to get the reference to the object's instance.

val factory = getInstance[ServiceFactory]("my.package.MyServiceFactory")
val service = factory.create()

这两种情况的问题是验证类型继承并确保它是一个单例对象.检查类似乎很简单,但考虑到所有 文档我能理解,没有人帮助我实现类似 isSingletonObject(name: String): Boolean 之类的东西:

The problem to both scenarios is verifying the type inheritance and making sure it is a singleton object. Checking the class seems straight-forward but given all the documentation I could understand, none helped me implementing something like isSingletonObject(name: String): Boolean as used in:

import scala.reflect.runtime.{universe => ru}
val rm = ru.runtimeMirror(classLoader)

def getInstance[T](name: String)(implicit tt: ru.TypeTag[T]): T = {
  if (!isSingletonObject(name)) throw new RuntimeException(
    s"$name does not specify a singleton object")
  val moduleSym = try rm.staticModule(name).asModule
  if (!(moduleSym.moduleClass.asClass.selfType <:< tt.tpe))
      throw new RuntimeException("Type of loaded module " + moduleSym.fullName
        + " does not satisfy subtype relationship with "
        + tt.tpe.typeSymbol.fullName)
  val mm = rm.reflectModule(moduleSym.asModule)
  mm.instance.asInstanceOf[T]
}

如何找到对象并验证给定的名称确实是一个对象?也欢迎针对给定场景使用其他方法.

How can one find objects and verify that a given name is really an object? Alternative approaches to the given scenarios are also welcome.

推荐答案

对于第一个问题,您可以使用 ClassUtil 库.请注意,它会找到 Java 类,而对应于 object 的类的名称将以 $class 结尾.另请参阅 Scala 反射 - 基于 trait 加载或查找类.

For the first question, you could use ClassUtil library. Note that it'll find Java classes, and the ones which correspond to objects will have names ending in $class. See also Scala Reflection - Loading or finding classes based on trait.

对于第二个,objects 在Scala反射中被称为模块",所以你不需要isSingletonObject(name);如果不是,代码中的 rm.staticModule(name).asModule 将会失败.似乎没有办法检查它是否是编译器生成的空伴随对象(isSynthetic 返回 false),但无论如何它们都会被子类型检查排除(静态部分也是如此)Java 类,但您也可以使用 isJava 过滤掉它们.

For the second, objects are called "modules" in Scala reflection, so you don't need isSingletonObject(name); if it isn't, rm.staticModule(name).asModule in your code will fail. There doesn't seem to be a way to check if it's a compiler-generated empty companion object (isSynthetic returns false), but they will be ruled out by the subtyping check anyway (so will the static parts of Java classes, but you can also filter those out using isJava).

这篇关于使用 Scala 的运行时反射查找对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆