-
-
Save programmerr47/dcf38e025383fcd06815fc669e85eec4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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