【问题标题】:Dynamic object method invocation using reflection in scala在scala中使用反射的动态对象方法调用
【发布时间】:2014-07-25 09:57:38
【问题描述】:

我正在寻找一种方法来根据 scala 中的模板 ID 动态调用逻辑。所以模板 id 1 调用逻辑 a,模板 id 2 调用逻辑 b,等等。逻辑将是多种多样的,但将具有相同的输入/输出。此外,不同模板 id 的数量将达到数千个,并且不会提前知道,因此松散耦合感觉是要走的路。

我已经开始考虑使用 scala 2.11.1 进行反射,并且当我知道要提前使用的逻辑但没有找到动态使用反射的正确方法时可以静态使用反射,例如传递在模板 id 2 中将调用逻辑 b。

下面是一个简化的示例,展示了静态版本的工作原理以及我目前所拥有的动态版本的骨架。

package thePackage

import scala.reflect.runtime.{universe => ru}

trait theTrait { def theMethod(x: String): Unit }

// the different logic held in different objects
object object1 extends theTrait {
  def theMethod(x: String) = { println("a " + x ) }
}

object object2 extends theTrait { 
  def theMethod(x: String) = { println("b " + x ) }
}

object object3 extends theTrait {
  def theMethod(x: String) = { println("c " + x ) }
}

// run static/dynamic reflection methods
object ReflectionTest {

  // "static" invocation calling object1.theMethod
  def staticInvocation() = {
    val m = ru.runtimeMirror(getClass.getClassLoader)
    val im = m.reflect(thePackage.object1)
    val method = ru.typeOf[thePackage.object1.type]
                   .decl(ru.TermName("theMethod")).asMethod
    val methodRun = im.reflectMethod(method)
    methodRun("test")
  }

  staticInvocation

  // "dynamic" invocation using integer to call different methods
  def dynamicInvocation( y: Integer) = {
    val m = ru.runtimeMirror(getClass.getClassLoader)
    val module = m.staticModule("thePackage.object" + y)
    val im = m.reflectModule(module)

    //  stuck... static approach does not work here

  }

  dynamicInvocation(1)
  dynamicInvocation(2)
  dynamicInvocation(3)

}

需要在 dynamicInvocation 方法中添加/更改哪些内容才能使其正常工作,或者我应该使用其他方法吗?

【问题讨论】:

    标签: scala reflection


    【解决方案1】:

    您需要为您的模块获取一个实例镜像,您可以在该镜像上反映该方法。

    def dynamicInvocation( y: Integer) = {
      val m = ru.runtimeMirror(getClass.getClassLoader)
      val module = m.staticModule("thePackage.object" + y)
      val im = m.reflectModule(module)
      val method = im.symbol.info.decl(ru.TermName("theMethod")).asMethod
    
      val objMirror = m.reflect(im.instance)
      objMirror.reflectMethod(method)("test")
    }
    

    【讨论】:

      【解决方案2】:

      似乎上述解决方案中的 TermName 方法已被 newTermName 替换,并且 info.decl 似乎不起作用。下面一行对我有用

      val method = im.symbol.typeSignature.member(ru.newTermName("testMethod")).asMethod
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-30
        • 2023-04-05
        • 1970-01-01
        • 2012-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-25
        相关资源
        最近更新 更多