Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin反射:如何通过反射将KFunction添加到列表中?_Kotlin_Reflection - Fatal编程技术网

Kotlin反射:如何通过反射将KFunction添加到列表中?

Kotlin反射:如何通过反射将KFunction添加到列表中?,kotlin,reflection,Kotlin,Reflection,我想根据类型在运行时添加到MutableListUint>。我基本上得到了它,但我不知道如何将实例信息输入到我拥有的k函数中 这段代码有点做作,但它是我试图做的一个简单的例子。我试图通过在运行时连接分派来摆脱一堆锅炉板代码 此代码可编译,但在运行时使用包含以下错误的列表时会爆炸: java.lang.IllegalArgumentException:Callable需要2个参数,但提供了1个。在分派时从doSomeWork()中 此错误使我认为实例与我要添加到列表中的KFunction没有关联。

我想根据类型在运行时添加到
MutableListUint>
。我基本上得到了它,但我不知道如何将实例信息输入到我拥有的
k函数中

这段代码有点做作,但它是我试图做的一个简单的例子。我试图通过在运行时连接分派来摆脱一堆锅炉板代码

此代码可编译,但在运行时使用包含以下错误的列表时会爆炸:
java.lang.IllegalArgumentException:Callable需要2个参数,但提供了1个。
在分派时从
doSomeWork()

此错误使我认为实例与我要添加到列表中的
KFunction
没有关联。。。但我不知道怎么把它联系起来。我手边有这个实例,我只是不知道如何附加它。或者完全是另外一回事

守则:

package reflectwork

import kotlin.reflect.KFunction
import kotlin.reflect.full.functions
import kotlin.reflect.full.hasAnnotation
import kotlin.reflect.full.memberProperties

interface Marker

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class WireMeUp

class Dispacher {
    val strList = mutableListOf<(String)->Unit>()
    val intList = mutableListOf<(Int)->Unit>()
    val floatList = mutableListOf<(Float)->Unit>()

    fun doSomeWork() {
        strList.forEach { it("Some work") }
        intList.forEach { it(57) }
        floatList.forEach { it(3.14f) }
    }
}


class Client : Marker {
    @WireMeUp fun doStringWork(str:String) { println(str) }
    @WireMeUp fun doIntWork(i:Int) { println(i) }
    @WireMeUp fun doFloatWork(f:Float) { println(f) }
}


fun wire(app:Marker, dis:Dispacher) {

    app::class.functions.forEach { func ->
        if( func.hasAnnotation<WireMeUp>() ) {
            require( func.parameters.size == 2 )
            val parmType = func.parameters[1].type

            dis::class.memberProperties.forEach{ prop ->
                if( prop.returnType.arguments.size == 1 ) {

                    val argType = prop.returnType.arguments[0].type
                    // I have no idea how to compare a [type] to a ([type]) -> Unit
                    // so just do it via strings. better way?
                    if( "($parmType)->kotlin.Unit" == argType.toString().replace(" ","")) {

                        println("found match, setting type = $parmType")
                        // get the list. No idea how cast to the correct type
                        // which in theory I know at this point.
                        val lst = prop.call(dis) as MutableList<KFunction<*>>

                        // this works, but blows up at runtime in doSomeWork()
                        // with the error :
                        // java.lang.IllegalArgumentException: Callable expects 2 arguments, but 1 were provided.
                        // I think because "func" has not instance? Not sure how to attach an instance... which I have
                        lst.add( func )

                    }
                }
            }

        }
    }
}


fun main() {

    val dispatch = Dispacher()
    val cli = Client()
    wire(cli,dispatch)
    dispatch.doSomeWork()
}
包反射工作
导入kotlin.reflect.k函数
导入kotlin.reflect.full.functions
导入kotlin.reflect.full.hasAnnotation
导入kotlin.reflect.full.memberProperties
接口标记
@目标(AnnotationTarget.FUNCTION)
@保留(AnnotationRetention.RUNTIME)
注释类WireMeUp
类分派器{
val strList=mutableListOfUnit>()
val intList=mutableListoUnit>()
val floatList=mutableListoUnit>()
有趣的工作{
strList.forEach{it(“一些工作”)}
intList.forEach{it(57)}
floatList.forEach{it(3.14f)}
}
}
类客户端:标记{
@WireMeUp-fun-doStringWork(str:String){println(str)}
@WireMeUp有趣的工作(i:Int){println(i)}
@WireMeUp-fun-doFloatWork(f:Float){println(f)}
}
娱乐线(应用程序:标记器,显示器){
app::class.functions.forEach{func->
if(func.hasaAnnotation()){
需要(func.parameters.size==2)
val parmType=func.parameters[1]。类型
dis::class.memberProperties.forEach{prop->
if(prop.returnType.arguments.size==1){
val argType=prop.returnType.arguments[0]。类型
//我不知道如何将[type]与([type])->单元进行比较
//所以只要通过字符串就行了。更好的方法?
如果(“($parmType)->kotlin.Unit”==argType.toString().replace(“,”)){
println(“找到匹配项,设置类型=$parmType”)
//获取列表。不知道如何转换为正确的类型
//理论上我现在知道了。
val lst=属性调用(dis)为可变列表
//这是可行的,但在doSomeWork()中运行时会崩溃
//错误如下:
//java.lang.IllegalArgumentException:Callable需要2个参数,但提供了1个。
//我想是因为“func”没有实例?不知道如何附加实例…我有
第一次添加(函数)
}
}
}
}
}
}
主要内容(){
val dispatch=dispatcher()
val cli=Client()
连线(cli,调度)
调度。doSomeWork()
}
有什么建议吗

提前谢谢

==更新====

@kyay的回答很有效,有点假惺惺。以下是适用于上述示例的相关代码:

                val lst = prop.call(dis) as MutableList<(Any)->Any>
                val withInstance = { param:Any -> func.call(app, param) as Any }
                lst.add( withInstance )
val lst=prop.call(dis)as MutableListAny>
val withInstance={param:Any->func.call(app,param)as Any}
lst.add(withInstance)

首先尝试将列表强制转换为
(Any)->Any
的lambda列表,然后添加一个lambda,该lambda使用关联的接收器调用您的KFunction,如下所示:

                        println("found match, setting type = $parmType")

                        val lst = prop.call(dis) as MutableList<(Any) -> Any>

                        lst.add( { param -> func.call(myReceiverInstance, param) } ) // You just need to supply the myReceiverInstance

                    }
println(“找到匹配项,设置类型=$parmType”)
val lst=属性调用(dis)为可变列表任意>
lst.add({param->func.call(myReceiveInstance,param)})//您只需要提供myReceiveInstance
}

是的。必须做一些转换,但是这段代码可以工作w/@kyay的回答:
val lst=prop.call(dis)as MutableListAny>val withInstance={param:Any->func.call(app,param)as Any}lst.add(withInstance)