Kotlin:使用反射设置带注释的 lateinit var
Kotlin: set annotated lateinit var using reflection
假设我尝试构建简单的依赖注入库。它的 Injector
class,当在特定的 class 上调用时,应该注入所有用 @Service
注释注释的属性。
例如,给定这个客户:
class ClientA {
@Service private lateinit var service1: Service1
@Service private lateinit var service2: Service2
private lateinit var service3: Service3
}
对 injector.inject(ClientA())
的调用应该导致 service1
和 service2
被设置(但不是 service3
)。假设 Injector
知道如何构造这些对象。
我的问题是如何编写解析 class' 属性、检查其注释并在 Kotlin 中设置它们的代码?
因为我在 Android,所以我试图通过 Java 反思:
fun inject(client: Any) {
val clientClass = client::class.java
val fields = clientClass.declaredFields
for (field in fields) {
if (isAnnotatedForInjection(field)) {
injectField(client, field)
}
}
}
private fun isAnnotatedForInjection(field: Field): Boolean {
val fieldAnnotations = field.annotations
for (annotation in fieldAnnotations) {
if (annotation is Service) {
return true
}
}
return false
}
问题是 fieldAnnotations
是空的。将 ClientA
的代码转换为 Java 我看到以下内容:
public final class ClientA {
private Service1 service1;
private Service2 service2;
private Service3 service3;
/** @deprecated */
// $FF: synthetic method
@Service
private static void service1$annotations() {
}
/** @deprecated */
// $FF: synthetic method
@Service
private static void service2$annotations() {
}
}
看起来 Kotlin 编译器创建了静态方法来聚合属性的注释。有了这些信息,我可以编写一些丑陋的代码来使用 Java 的反射 API,但必须有更简洁的方法,对吗?
如果要在字段上放置注释,可以使用@field:Service
。
假设我尝试构建简单的依赖注入库。它的 Injector
class,当在特定的 class 上调用时,应该注入所有用 @Service
注释注释的属性。
例如,给定这个客户:
class ClientA {
@Service private lateinit var service1: Service1
@Service private lateinit var service2: Service2
private lateinit var service3: Service3
}
对 injector.inject(ClientA())
的调用应该导致 service1
和 service2
被设置(但不是 service3
)。假设 Injector
知道如何构造这些对象。
我的问题是如何编写解析 class' 属性、检查其注释并在 Kotlin 中设置它们的代码?
因为我在 Android,所以我试图通过 Java 反思:
fun inject(client: Any) {
val clientClass = client::class.java
val fields = clientClass.declaredFields
for (field in fields) {
if (isAnnotatedForInjection(field)) {
injectField(client, field)
}
}
}
private fun isAnnotatedForInjection(field: Field): Boolean {
val fieldAnnotations = field.annotations
for (annotation in fieldAnnotations) {
if (annotation is Service) {
return true
}
}
return false
}
问题是 fieldAnnotations
是空的。将 ClientA
的代码转换为 Java 我看到以下内容:
public final class ClientA {
private Service1 service1;
private Service2 service2;
private Service3 service3;
/** @deprecated */
// $FF: synthetic method
@Service
private static void service1$annotations() {
}
/** @deprecated */
// $FF: synthetic method
@Service
private static void service2$annotations() {
}
}
看起来 Kotlin 编译器创建了静态方法来聚合属性的注释。有了这些信息,我可以编写一些丑陋的代码来使用 Java 的反射 API,但必须有更简洁的方法,对吗?
如果要在字段上放置注释,可以使用@field:Service
。