反射调用函数并使用默认参数
Reflectively calling function and using default parameters
给定以下函数
fun function(x: Int = 12) {
println("x = $x")
}
我如何在不指定 x
的情况下使用反射调用它(或者以某种方式使用默认值,而不是 对其进行硬编码)?
您可以使用 callBy
,它遵循默认值:
::function.callBy(emptyMap()) // is just function()
如果你有很多没有默认值的参数,事情会很混乱:
fun foo(a: Int, b: String = "") {}
val ref = ::foo
val params = ref.parameters
ref.callBy(mapOf(params[0] to 1)) // is just foo(1)
如果你的函数是一个非对象类型的成员函数,或者它是扩展函数,或者它是一个类型的扩展函数作为(其他)非对象的成员函数,那就更无聊了类型。
我写了一个减少样板文件的便捷方法:
fun <R> KFunction<R>.callNamed(params: Map<String, Any?>, self: Any? = null, extSelf: Any? = null): R {
val map = params.entries.mapTo(ArrayList()) { entry ->
parameters.find { name == entry.key }!! to entry.value
}
if (self != null) map += instanceParameter!! to self
if (extSelf != null) map += extensionReceiverParameter!! to extSelf
return callBy(map.toMap())
}
用法:
fun String.foo(a: Int, b: String = "") {}
fun foo(a: Int, b: String = "") {}
class Foo {
fun bar(a: Int, b: String = "") {}
fun String.baz(a: Int, b: String = "") {}
}
::foo.callNamed(mapOf("a" to 0))
String::foo.callNamed(mapOf("a" to 0), extSelf = "")
Foo::bar.callNamed(mapOf("a" to 0), Foo())
// function reference don't work on member extension functions
Foo::class.declaredFunctions.find { it.name == "baz" }!!.callNamed(mapOf("a" to 0), Foo(), "")
给定以下函数
fun function(x: Int = 12) {
println("x = $x")
}
我如何在不指定 x
的情况下使用反射调用它(或者以某种方式使用默认值,而不是 对其进行硬编码)?
您可以使用 callBy
,它遵循默认值:
::function.callBy(emptyMap()) // is just function()
如果你有很多没有默认值的参数,事情会很混乱:
fun foo(a: Int, b: String = "") {}
val ref = ::foo
val params = ref.parameters
ref.callBy(mapOf(params[0] to 1)) // is just foo(1)
如果你的函数是一个非对象类型的成员函数,或者它是扩展函数,或者它是一个类型的扩展函数作为(其他)非对象的成员函数,那就更无聊了类型。
我写了一个减少样板文件的便捷方法:
fun <R> KFunction<R>.callNamed(params: Map<String, Any?>, self: Any? = null, extSelf: Any? = null): R {
val map = params.entries.mapTo(ArrayList()) { entry ->
parameters.find { name == entry.key }!! to entry.value
}
if (self != null) map += instanceParameter!! to self
if (extSelf != null) map += extensionReceiverParameter!! to extSelf
return callBy(map.toMap())
}
用法:
fun String.foo(a: Int, b: String = "") {}
fun foo(a: Int, b: String = "") {}
class Foo {
fun bar(a: Int, b: String = "") {}
fun String.baz(a: Int, b: String = "") {}
}
::foo.callNamed(mapOf("a" to 0))
String::foo.callNamed(mapOf("a" to 0), extSelf = "")
Foo::bar.callNamed(mapOf("a" to 0), Foo())
// function reference don't work on member extension functions
Foo::class.declaredFunctions.find { it.name == "baz" }!!.callNamed(mapOf("a" to 0), Foo(), "")