Invoking Functions
Inspekt allows invoking functions that have been inspekted, including property accessors.
Of course, this only works if the function has a body that can be invoked.
If you are inspekting a concrete class, this is guaranteed.
But if the inspektion is of an abstract class, such as the interface for a proxy, some members may not be invokable.
To check this, check the isInvokable property.
Functions with reified type parameters are also not invokable, so it is important to use isInvokable instead of isAbstract.
You may also want to check isSuspend - attempting to invoke a suspending function using the invoke method (instead of invokeSuspend) will throw an error.
Inspektion also provides convenient shorthand utilities for invoking and accessing non-ambiguous member functions and properties, see Inspektion.
The Invoke function
The most common way to call a function is using the invoke method. It uses a lambda block to configure the arguments.
val foo = Foo()
val result = inspekt(Foo::bar).invoke {
dispatchReceiver = foo
value(arg1, arg2)
}
Arguments
All arguments are stored in a flat list matching the parameter order. The ordering of argument and parameter kinds matches that used by the Kotlin compiler:
- Dispatch receiver (if present)
- Context parameters
- Extension receiver (if present)
- Value parameters
The invoke lambda's receiver, ArgumentList.Builder, provides many utilities for setting arguments:
dispatchReceiverextensionReceiverthis[Kind, index] = valuecontext(context1, context2, ...)value(value1, value2, ...)- And more – see the API documentation.
To use the default value of an argument, do not set it.
Setting an argument to null actually passes null and will not use the default.
Some limited type checking is done for arguments before calling the method, but it is limited to what is available at runtime using KType.
Suspend Functions
Invoking suspend functions is just as easy, but you must use the invokeSuspend method within a coroutine or another suspend function:
suspend fun example() {
val result = inspekt(Foo::asyncTask).invokeSuspend {
dispatchReceiver = Foo()
value("some data")
}
}
Calling invoke on a suspend function will throw an exception.
Calling invokeSuspend on a non-suspend function will work fine, and just call the non-suspending invoker.
Properties
You can also get and set property values using a similar syntax:
val value = prop.get { dispatchReceiver = foo }
prop.set {
dispatchReceiver = foo
value(newValue)
}
or by using invoke on their getter or setter:
prop.getter.invoke { dispatchReceiver = foo }