Skip to content

Instantly share code, notes, and snippets.

@yongjhih
Last active October 20, 2023 17:39
Show Gist options
  • Save yongjhih/4281d61127cf92ba68202a8f935807a6 to your computer and use it in GitHub Desktop.
Save yongjhih/4281d61127cf92ba68202a8f935807a6 to your computer and use it in GitHub Desktop.
inline fun <reified T> Any.getDeclaredFieldValue(fieldName: String): T =
javaClass.findDeclaredField(fieldName).run {
if (!isAccessible) isAccessible = true
get(this@getDeclaredFieldValue) as T
}
inline fun <reified T> Any.getDeclaredFieldValueOrNull(fieldName: String): T? =
try { getDeclaredFieldValue(fieldName) }
catch (e: NoSuchFieldException) { null }
catch (e: SecurityException) { null }
catch (e: IllegalArgumentException) { null }
catch (e: IllegalAccessException) { null }
fun <T: Any> Class<T>.findDeclaredField(fieldName: String): Field {
var klass: Class<*>? = this
var ex: NoSuchFieldException? = null
while (klass != null) {
try { return klass.getDeclaredField(fieldName) }
catch (e: NoSuchFieldException) { ex = ex ?: e }
klass = klass.superclass
}
throw ex ?: NoSuchFieldException(fieldName)
}
fun <T: Any> Class<T>.findDeclaredMethod(name: String, onParameters: TypedValues.() -> Unit = {}): Method {
var klass: Class<*>? = this
var ex: ReflectiveOperationException? = null
val (types, values) = TypedValues().apply(onParameters).list.unzip()
while (klass != null) {
try { return klass.getDeclaredMethod(name, *(types.toTypedArray())) }
catch (e: ReflectiveOperationException) { ex = ex ?: e }
klass = klass.superclass
}
throw ex ?: NoSuchMethodException(name)
}
fun <T: Any> Class<T>.getDeclaredFieldOrNull(fieldName: String): Field? =
try { getDeclaredField(fieldName) }
catch (e: NoSuchFieldException) { null }
class TypedValues {
val list: MutableList<Pair<Class<*>, Any?>> = mutableListOf()
@JvmName("addPair")
fun <T: Any> add(pair: Pair<Class<T>, T?>) = list.add(pair)
@JvmName("addNullablePrimitive")
inline fun <reified T: Any> add(value: T?) = add((T::class.javaPrimitiveType ?: T::class.java) to value)
}
/**
* Usage:
*
* ```
* val result = obj.invokeMethod<String>("methodName") {
* ```
*/
inline fun <reified R> Any.invokeMethod(name: String, noinline onParameters: TypedValues.() -> Unit = {}): R = run {
val (types, values) = TypedValues().apply(onParameters).list.unzip()
javaClass.findDeclaredMethod(name, onParameters).run {
if (!isAccessible) isAccessible = true
invoke(this@invokeMethod, *(values.toTypedArray())) as R
}
}
inline fun <reified R> Any.invokeMethodOrNull(name: String, noinline onParameters: TypedValues.() -> Unit = {}): R? =
try { invokeMethod(name, onParameters) }
catch (e: NoSuchMethodException) { null }
catch (e: SecurityException) { null }
catch (e: IllegalArgumentException) { null }
catch (e: IllegalAccessException) { null }
catch (e: InvocationTargetException) { null }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment