如何通过反射运行暂停方法? [英] How to run suspend method via reflection?

查看:115
本文介绍了如何通过反射运行暂停方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个协程块可以运行挂起功能.

There is an coroutine block that can runs suspend functions.

但是我通过反射通过invoke调用了该函数.这是java样式的调用,显然,简单的调用将不起作用. 有没有办法异步运行反射方法?如何等待这种方法?

But I call the function by invoke via reflection. This is java style invocation, apparently a simple call will not work. Are there ways to run reflected method asynchronously? How to await this method?

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 

        }
    }
}

推荐答案

更新

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

Since Kotlin 1.3 reflection natively supports calling suspending functions via KFunction.callSuspend and KFunction.callSuspendBy, so the above workaround is no longer needed.

原始答案

Kotlin中的每个suspend方法都通过CPS转换在JVM上表示,这在

Every suspend method in Kotlin is represented on JVM via CPS transformation that is explained in the coroutines design document. Java reflection is not aware about it and Kotlin reflection does not currently provide convenient means to perform invocation of suspending function either.

您将必须通过助手功能自行进行CPS转换的调用.我建议为此目的实现以下帮助程序:

You'll have to do invocation with CPS transformation yourself via helper function. I'd suggest to implement the following helper for this purpose:

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,则它将按预期工作.

Now if you replace invoke with invokeSuspend in your code, then it is going to work just like expected.

这篇关于如何通过反射运行暂停方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆