如何通过反射运行悬挂方法



有一个可以运行悬挂函数的coroutine块。

,但我通过反射通过invoke调用该功能。这是Java样式调用,显然一个简单的调用将无法使用。是否有方法可以异步运行反射方法?如何等待此方法?

import kotlin.coroutines.experimental.*
class TestClass(val InString: String) {
    suspend fun printString() {
        println(InString)
    }
}
fun launch(context: CoroutineContext, block: suspend () -> Unit) =
        block.startCoroutine(StandaloneCoroutine(context))
private class StandaloneCoroutine(override val context: CoroutineContext): Continuation<Unit> {
    override fun resume(value: Unit) {}
    override fun resumeWithException(exception: Throwable) {
        val currentThread = Thread.currentThread()
        currentThread.uncaughtExceptionHandler.uncaughtException(currentThread, exception)
    }
}
fun main(args: Array<String>) {
    launch(EmptyCoroutineContext) {
        val a = TestClass("TestString");
        for (method in a.javaClass.methods) {
            if (method.name == "printString")
                method.invoke(a)  // Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments 
        }
    }
}

update

由于Kotlin 1.3反射本质地支持通过KFunction.callSuspendKFunction.callSuspendBy调用暂停功能,因此不再需要上述解决方法。

原始答案

Kotlin中的每个suspend方法都通过CPS转换在JVM上表示,这在Coroutines设计文档中进行了解释。Java反射不知道这一点,Kotlin反射目前没有提供方便的手段来执行悬挂功能的调用。

您必须通过辅助功能自己进行CPS转换的调用。我建议为此目的实施以下帮手:

import java.lang.reflect.Method
import kotlin.coroutines.experimental.intrinsics.*
suspend fun Method.invokeSuspend(obj: Any, vararg args: Any?): Any? =
    suspendCoroutineOrReturn { cont ->
        invoke(obj, *args, cont)
    }

现在,如果您在代码中将invoke替换为invokeSuspend,那么它将像预期一样工作。

您可以使用kotlin反射并致电suspend如下:

suspend fun Any.invokeSuspendFunction(methodName: String, vararg args: Any?): Any? =
        this::class.memberFunctions.find { it.name == methodName }?.also {
            it.isAccessible = true
            return it.callSuspend(this, *args)
        }

相关内容

  • 没有找到相关文章

最新更新