0

I'm looking to create a way to dynamically call logic depending on template id within scala. So template id 1 calls logic a, template id 2 call logic b, etc. The logic will be diverse but will have the same inputs/outputs. Also the number of different template ids will get into the thousands and will not be known ahead of time, so a loose coupling feels the way to go.

I've started looking at reflection to do this using scala 2.11.1 and can statically use reflection when I know the logic to be used ahead of time but have not found the correct way to dynamically use reflection, so for example passing in template id 2 will call logic b.

Below is a cut down example showing how the static version works and the skeleton I have so far for the dynamic version.

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)

}

What needs to be added/changed to the dynamicInvocation method to make this work, or should I be using a different approach?

2 Answers 2

5

You need to get an instance mirror for your module, on which you can reflect the method.

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")
}
Sign up to request clarification or add additional context in comments.

Comments

1

It seems that TermName method in above solution has been replaced by newTermName and also the info.decl seems to not work. Below line worked for me

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.