如何在Kotlin通用代码中创建动态代理?

Ada*_*old 5 proxy-pattern kotlin kotlin-multiplatform

如果我在 JVM 上,我可以这样做:

object Playground {

    class DynamicInvocationHandler : InvocationHandler {

        @Throws(Throwable::class)
        override operator fun invoke(proxy: Any, method: Method, args: Array<Any>): Any {
            LOGGER.info("Invoked method: {}", method.name)

            return 42
        }

        companion object {

            private val LOGGER = LoggerFactory.getLogger(
                    DynamicInvocationHandler::class.java)
        }
    }

    @JvmStatic
    fun main(args: Array<String>) {
        val proxy = Proxy.newProxyInstance(
                Playground::class.java.classLoader,
                arrayOf<Class<*>>(MutableMap::class.java),
                DynamicInvocationHandler()) as MutableMap<String, String>

        proxy["foo"] = "bar"
    }
}
Run Code Online (Sandbox Code Playgroud)

运行此命令将打印Invoked method: put. 我怎样才能在 Kotlin公共项目中做这样的事情?

编辑:我不想在我的公共模块中使用 Java 中的任何内容。我知道常见项目是如何运作的。我感兴趣的是是否有基于 Kotlin 的解决方案。

编辑2:我不想代理该类Map。我正在寻找类似ProxyJDK 中的东西,我可以用它来代理任何接口。对困惑感到抱歉。

Den*_*gin 1

也许 Expect/Actual Factory 应该可以解决问题。

通用代码:

interface ProxyMethod {
    val name: String
    // other properties
}

interface ProxyHandler {
    fun invoke(proxy: Any, method: ProxyMethod, args: Array<Any>): Any
}

expect object Logger {
    fun info(message: String, vararg arguments: Any)
}

expect object ProxyFactory {
    fun mutableMapWithProxy(handler: ProxyHandler): MutableMap<String, String>
}

private class ProxyHandlerImpl: ProxyHandler {
    override fun invoke(proxy: Any, method: ProxyMethod, args: Array<Any>): Any {
        Logger.info("Invoked method: {}", method.name)
        return 0
    }
}

object Common {
    fun doSomething() {
        val myMap = ProxyFactory.mutableMapWithProxy(ProxyHandlerImpl())
        myMap["foo"] = "bar"
    }
}
Run Code Online (Sandbox Code Playgroud)

Java代码:

actual object Logger {

    private val instance = LoggerFactory.getLogger(
            DynamicInvocationHandler::class.java)

    actual fun info(message: String, vararg arguments: Any) {
        instance.info(message, *arguments)
    }
}

actual object ProxyFactory  {
    actual fun mutableMapWithProxy(handler: ProxyHandler): MutableMap<String, String> {
        return Proxy.newProxyInstance(
                Playground::class.java.classLoader,
                arrayOf<Class<*>>(MutableMap::class.java),
                ProxyHandlerAdapter(handler)) as MutableMap<String, String>
    }
}

class ProxyHandlerAdapter(private val handler: ProxyHandler) : InvocationHandler {

    @Throws(Throwable::class)
    override operator fun invoke(proxy: Any, method: Method, args: Array<Any>): Any {
        return handler.invoke(proxy, methodToProxyMethod(method), args)
    }

    fun methodToProxyMethod(method: Method): ProxyMethod {
        // convert Method to ProxyMethod
    }
}

@JvmStatic
fun main(args: Array<String>) {
    Common.doSomething()
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我不知道有任何库可以简化这项工作,因此您应该为每个平台和界面手动执行此操作。