简体   繁体   中英

Scala: Reflection APIs to call one of the two methods with the same name

I am trying to use Scala Reflection APIs to call one of the two methods with the same name. Only difference is that one of them takes an argument but the other one doesn't. I want to call the one that doesn't take any arguments. I am trying something like this:

  val ru = scala.reflect.runtime.universe
  val rm = ru.runtimeMirror(getClass.getClassLoader)
  val instanceMirror = rm.reflect(myInstance)
  val methodSymbol = instanceMirror.symbol.typeSignature.member(ru.TermName("getXyzMethod")).asTerm.alternatives

  if (methodSymbol != null && methodSymbol.nonEmpty) {
    try {
      val method = instanceMirror.reflectMethod(methodSymbol.head.asMethod)
      val value = method()
      }
    } catch {
      case e: java.lang.IndexOutOfBoundsException =>
        val method = instanceMirror.reflectMethod(methodSymbol.last.asMethod)
        val value = method()

      case e: Exception =>
    }
  }

This works but as you can see this is a bit ugly. The reason for doing it this way is that the 'methodSymbol' is a list in which the method I want is sometimes in the 'head' position & sometimes in the 'last' position.

How do I use Scala Reflection APIs to get only the method that I want which has no arguments?

You can do something like this:

  val ru: JavaUniverse = scala.reflect.runtime.universe
  val rm: ru.Mirror = ru.runtimeMirror(getClass.getClassLoader)
  val instanceMirror: ru.InstanceMirror = rm.reflect(myInstance)

  val methodSymbol: Seq[ru.Symbol] =
    instanceMirror.symbol.typeSignature.member(ru.TermName("getXyzMethod")).asTerm.alternatives
  val maybeMethods: Try[ru.MethodSymbol] = Try(methodSymbol.map(_.asMethod).filter(_.paramLists.flatten.isEmpty).head)


  val result: ru.MethodMirror = maybeMethods match {
    case Failure(exception) => //do something with it
      throw new Exception(exception)
    case Success(value) => instanceMirror.reflectMethod(value)
  }

  println(result)

This will always return the method with no parameters.

Being like this:

def getXyzMethod() = ???

or

def getXyzMethod = ???

Adjust the size of the sequence if that method as more parameters, so if the method you want has exactly 1 parameter:

val maybeMethods: Try[ru.MethodSymbol] = Try(methodSymbol.map(_.asMethod).filter(_.paramLists.flatten.size==1).head)

And so on, hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM