I try to call methods by reflection in kotlin and it doesn't work.
My code (simplyfied, null-checks and catch-exceptions omitted):
class MyCallerClass() {
val allCallableMethods: List<KFunction<Unit>> = ...
// request: we're within a web-page. The user can see the callable methods and click which one to call
fun handleRequest(request: HttpServletRequest) {
val callableMethodName = request.getParameter(callableMethodNameParam)
if (callableMethodName != null) {
for (method in allCallableMethods) {
if (method.name == callableMethodName) {
// we found the method the user wants to call!
val paramMap: MutableMap<KParameter, Any> = mutableMapOf()
// this part I added after I got an IllegalArgumentException. See below
if (method is CallableReference) {
paramMap[method.instanceParameter!!] = method.owner
}
for (param in method.valueParameters) {
val paramName = if (param.name != null) {
param.name!!
}
val paramValue: String? = request.getParameter(paramName)
if(paramValue != null) {
paramMap[param] = paramValue
}
}
method.callBy(paramMap)
}
}
}
}
}
So first I only collected all params in the paramMap, but that resulted in "java.lang.IllegalArgumentException: No argument provided for a required parameter: instance parameter of fun...".
Luckily I found questions here that helped me on:
- Error when use callBy on a function with default parameters in Kotlin
- Is there a way to get Kotlin function's owner via reflection
So I added the part with if (method is CallableReference)
. But now I get a "java.lang.IllegalArgumentException: object is not an instance of declaring class".
I also tried to use method.call()
instead of method.callBy()
:
...
var paramArray = arrayOf<Any>()
...
paramArray = paramArray.plus(paramValue)
...
method.call(*paramArray)
But that gave the same results. Without the instance-parameter I get a "java.lang.IllegalArgumentException: Callable expects 2 arguments, but 1 were provided.". With the instance-parameter the same "java.lang.IllegalArgumentException: object is not an instance of declaring class"
Then I tried to call a method within the same class: I created a new method in MyCallerClass:
fun myLocalMethod(strParam: String, intParam: Int): String {
return strParam
}
and then I added this in fun handleRequest
:
val myLocalMethodFunc = ::myLocalMethod
val returnStr = myLocalMethodFunc.call("test", 3)
And it worked! o_O
So can anyone explain
- why the call to the local function works and to the remote function doesn't? They're both of the type KFunction.
- how I can call the remote functions? How do I provide the instanceParameter in the correct way?
- why I can't debug into
method.callBy()
ormethod.call()
? That would help me a lot, but IntelliJ just jumps over it.
Aucun commentaire:
Enregistrer un commentaire