2

2つのクラスがあるとしましょう:

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 に渡すにはどうすればよいですか?

ありがとう。

4

1 に答える 1

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) _ )

(*) これはテストされていませんが、正しい方向にあるはずです。システムの一部で同様の構造を使用しています。

于 2013-10-02T08:05:57.920 に答える