Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin:使用反射设置带注释的lateinit变量_Kotlin_Reflection_Annotations - Fatal编程技术网

Kotlin:使用反射设置带注释的lateinit变量

Kotlin:使用反射设置带注释的lateinit变量,kotlin,reflection,annotations,Kotlin,Reflection,Annotations,想象一下,我试图构建简单的依赖项注入库。它的Injector类在对特定类调用时,应该注入用@Service注释注释的所有属性 例如,给定此客户端: class ClientA { @Service private lateinit var service1: Service1 @Service private lateinit var service2: Service2 private lateinit var service3: Service3 } 调用injec

想象一下,我试图构建简单的依赖项注入库。它的
Injector
类在对特定类调用时,应该注入用
@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
知道如何构造这些对象

我的问题是如何编写代码来解析类的属性、检查它们的注释并在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

它是用于运行时还是编译时操作?您尝试过
@field:Service
?@EpicPandaForce,它可以工作。谢谢把它贴出来作为答案,这样我就可以接受了。现在对我来说已经足够好了,但是在Kotlin中检查运行时注释难道没有更好的选择吗?一些“Kotlin-ish”?有Kotlin-Reflect,但它很大,我没有使用过,所以我现在对它了解得不够。我确信Dagger做了一些事情,消除了在
对象
中使用@JvmStatic的需要,因此可能会有类似的更新,不再需要
@field:
。我想知道他们是否只是检查两者……这里的要点是Kotlin为每个属性生成一个字段和访问器方法,默认情况下注释应用于后者
@字段:
改变了这一点。细节。(顺便说一句,反射是一个经常被滥用的工具;在我看来,关于它的大多数问题可能都应该使用其他工具来代替。依赖注入是它非常适合的罕见的事情之一!)