我如何通过反思来获得物业的价值?
我想使用具有一些注释的所有属性的值。 在大多数情况下,我的代码工作,我得到所有的属性,只拿那些注释。
private inline fun <reified A : Annotation> (target: Any) { target::class.memberProperties .filter { it.annotations.any { annotation -> annotation is A } } .forEach { // How do I get the value here? } }
我想使用it.get(...)
但期望一个Nothing
作为参数。 getter
。 调用它it.call(target)
确实有效,但是看起来不对,因为有一个我不知道如何调用的调用。
那么获取属性值的正确方法是什么?
问题归结为T::class
给你一个KClass<T>
的事实,而t::class
给你一个KClass<out T>
。 考虑以下几点:
class Foo { val foo = 2 val bar = 3 } fun f() { val any: Any = Foo() any::class.memberProperties.forEach { println(it.get(2)) // Oops } }
这本质上会尝试访问2.foo
和2.bar
,但是它不被允许,因为在谨慎的方面get
错误,而不是允许Any
类型的参数。 看来做t.javaClass.kotlin
会产生一个KClass<T>
,但是。 如上所述滥用它会导致IllegalArgumentException
。
您可以通过提供编译时保证KClass
将用于类型,而不是别的:
private inline fun <reified A : Annotation, reified T : Any> foo(target: T) { T::class.memberProperties .filter { it.annotations.any { annotation -> annotation is A } } .forEach { println(it.get(target)) } }
不幸的是,我不知道在从target
推导出T
A
时候是否可以指定A
我还没有找到一种方式来调用它像foo<Attr, Bar>(bar)
。
或者,你可以通过javaClass
,虽然我敢打赌,它不太便携:
private inline fun <reified A : Annotation> foo(target: Any) { target.javaClass.kotlin.memberProperties .filter { it.annotations.any { annotation -> annotation is A } } .forEach { println(it.get(target)) } }
我们知道这不会遇到上述问题,因为我们在两种情况下都传递相同的对象。 这也看起来更好的来电方,这可能是值得的便携性打击,假设有一个。