mercredi 11 novembre 2020

Invoke static method with access only to the containing object's type

I have a TypeTag for one of several objects and I know that they extend a base trait with a known method signature. I also have access to the method's MethodSymbol if I need it. What I want to do is:

def invokeMyMethod[T: TypeTag](myMethodSymbol: MethodSymbol): String = {
  // I know T has structural type { def myMethod: String }
  // so I want the result of calling T.myMethod but I don't have
  // access to the actual object T, only its type.
}

Since I know the type represents an object, I know that the method is static and so I just need access to the singleton instance to be able to invoke the method. Unfortunately I can't find a way to get from the type to the instance.

I know I can obtain a RuntimeClass instance from a runtimeMirror, but I'm not sure what to do with that class once I have it. It seems to essentially have type AnyRef, so I tried casting it with no luck:

def invokeMyMethod[T: TypeTag]: Any = {
  val runtimeT = runtimeMirror(getClass.getClassLoader).runtimeClass(T)
  runtimeT.asInstanceOf[{ def myMethod: String }].myMethod
  // Error invoking method 'myMethod'
}

I also know I can get a ClassMirror from my ClassSymbol but that only seems to give access to the constructor MethodMirror which doesn't help if my item is an object and not a class:

def invokeMyMethod[T: TypeTag](myMethodSymbol: MethodSymbol): Any = {
  val mirror = runtimeMirror(getClass.getClassLoader)
  val runtimeT = mirror.runtimeClass(T)
  val mirrorT = mirror.reflect(runtimeT)
  mirrorT.reflectMethod(myMethodSymbol)()
  // Expected a member of class Class, you provided value T.myMethod
}

And I know if I had the actual runtime instance of T it would be easy with an InstanceMirror but I can't figure out how to get the InstanceMirror of my object type.





Aucun commentaire:

Enregistrer un commentaire