【问题标题】:How to run suspend method via reflection?如何通过反射运行挂起方法?
【发布时间】:2018-05-19 04:02:27
【问题描述】:

有一个协程块可以运行挂起函数。

但我通过反射调用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 

        }
    }
}

【问题讨论】:

标签: java kotlin async-await coroutine kotlin-coroutines


【解决方案1】:

更新

由于 Kotlin 1.3 反射原生支持通过 KFunction.callSuspendKFunction.callSuspendBy 调用挂起函数,因此不再需要上述解决方法。

原答案

Kotlin 中的每个suspend 方法都通过coroutines design document 中解释的 CPS 转换在 JVM 上表示。 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 1.3,则应将 suspendCoroutineOrReturn 更改为 suspendCoroutineUninterceptedOrReturn
  • 请注意,函数 kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn 不是 intelliJ 通过自动导入找到的:您必须手动导入它,或者在键入时完全限定它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 2014-12-02
  • 2014-07-10
  • 1970-01-01
相关资源
最近更新 更多