假设我有两个班级:
class A {
def sayHello(name: String) {
println("Hi " + name)
}
}
class B {
var methodMaps = Map[String, String => Unit]()
def registerMethod(methodName: String, method: String => Unit) {
methodMaps += (methodName -> method)
}
}
好的,通常情况下,我会打电话给:
val b = new B
val a = new A
b.registerMethod("sayHello", a.sayHello)
但现在我想将信息放入配置文件中,例如:
<method class="A" name="sayHello" />
现在,在代码中它需要是这样的:
val b = new B
val className = readFromConfig()
val methodName = readFromConfig()
val aInstance = createInstanceFromReflection(className)
b.registerMethod(methodName, ...)
问题是我不知道如何让a.sayHello传递给registerMethod,我可以为sayHello获取MethodMirror,但是如何将它传递给registerMethod?
感谢。
答案 0 :(得分:0)
我想在你的情况下,你需要简单的旧反思。在您的示例中,在表达式b.registerMethod("sayHello", a.sayHello)
中,Scala编译器会将a.sayHello
提升为函数。
当您使用文件中的动态类数据时,编译器无法帮助您;这意味着你需要自己做这项工作。按照你自己的例子,我们应该:
val className = readFromConfig()
val methodName = readFromConfig()
val clazz = Class.forName(className)
val method = clazz.getMethods.find(x=>x.getName == "methodName" && x.getParameterTypes().length==1)
val aInstance = clazz.newInstance()
def invoke1[T,U](obj:Any, method:Method)(param:T):U = method.invoke(obj,Seq(param.asInstanceOf[java.lang.Object]):_*).asInstanceOf[U]
现在你应该可以在你的地图中注册这样的构造:
registerMethod(methodName, invoke1(aInstance,method) _ )
(*)这未经过测试,但应该是正确的方向,我们在系统的某些部分使用类似的结构。