Skip to content

Instantly share code, notes, and snippets.

@programmerr47
Created May 28, 2020 05:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save programmerr47/dcf38e025383fcd06815fc669e85eec4 to your computer and use it in GitHub Desktop.
Save programmerr47/dcf38e025383fcd06815fc669e85eec4 to your computer and use it in GitHub Desktop.
internal fun Any.getMethod(name: String): ObjectMethod? =
getMember { declaredMethods.find { it.name == name } }?.let { ObjectMethod(this, it) }
internal fun <T> Any.getField(fieldGetter: () -> Field) =
runCatching { fieldGetter() }.getOrNull()?.let { ObjectField<T>(this, it) }
private fun <T : Member> Any.getMember(membersGetter: Class<Any>.() -> T?): T? = throughHierarchy { membersGetter() }
private fun <T> Any.throughHierarchy(invoke: Class<Any>.() -> T?): T? {
var clz: Class<in Any>? = javaClass
while (clz != null) {
invoke(clz)?.let { return it }
clz = clz.superclass
}
return null
}
internal class ObjectMethod(
private val what: Any,
private val method: Method
) {
operator fun invoke(vararg args: Any) = runCatching { method.withAccessible { invoke(what, *args) } }
.onFailure { Timber.e(it) }
}
internal class ObjectField<T>(
private val what: Any,
private val fld: Field
) {
var value: T?
get() = runCatching { fld.withAccessible { get(what) } }
.onFailure { Timber.e(it) }
.getOrNull() as? T
set(new) {
runCatching { fld.withAccessible { set(what, new) } }
.onFailure { Timber.e(it) }
}
}
private inline fun <T : AccessibleObject, R> T.withAccessible(block: T.() -> R): R {
val prev = isAccessible
isAccessible = true
val result = runCatching { block() }
isAccessible = prev
return result.getOrThrow()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment