【问题标题】:Kotlin - return all properties that implement an interface and are annotatedKotlin - 返回所有实现接口并被注释的属性
【发布时间】:2023-02-21 01:39:09
【问题描述】:

我有一个简单的 kotlin 1.7.10 程序 - 我有一个名为 Rule 的接口和名为 NextRule 的属性注释 + 2 个实现

import kotlin.reflect.KClass

interface Rule {
    fun process(s: String): String
}

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class NextRule


class EndRule() : Rule {

    override fun process(s: String) = "$s END"
}

class StartRule(
    @NextRule
    private val endRule: EndRule
) : Rule {
    override fun process(s: String): String = "$s START"
}

我想创建一个函数,该函数将采用实现Rule接口的对象并为每个字段返回,该对象也实现Rule并用NextRule注释其KClass - 基本上是一个类似于Rule -> Seq<KClass<out Rule>>的函数 - 一些东西喜欢

fun getAllNextRuleAnnotatedClasses(rule: Rule): List<KClass<out Rule>> {
    for(property in rule::class.properties){
        if(property.returnType.class implements Rule && property isAnnotatedWith NextRule){
            yield property::class
        }
    }
}

如何实现?

【问题讨论】:

    标签: kotlin kotlin-reflect


    【解决方案1】:

    你可以试试这个:

    fun getAllNextRuleAnnotatedClasses(rule: Rule): List<KClass<out Rule>> {
        return rule::class.memberProperties
            .filter { it.returnType.classifier == Rule::class }
            .filter { it.findAnnotation<NextRule>() != null }
            .map { it.returnType.classifier as KClass<out Rule> }
    }
    

    【讨论】:

      【解决方案2】:

      我设法解决了

      @Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE_PARAMETER)
      @Retention(AnnotationRetention.RUNTIME)
      @MustBeDocumented
      annotation class NextRule
      
      fun getAllNextRuleAnnotatedClasses(rule: Rule): List<Rule> {
          return sequence {
              rule::class.primaryConstructor!!.parameters.forEach { param ->
                  if (param.type.jvmErasure.isSubclassOf(Rule::class) && param.findAnnotation<NextRule>() != null) {
                      val field = rule::class.java.getDeclaredField(param.name!!)
                      val isAccessible = field.canAccess(rule)
                      if (!isAccessible) {
                          field.setAccessible(true);
                      }
                      val value = field.get(rule) as Rule
                      if (!isAccessible) {
                          field.setAccessible(false);
                      }
                      yield(value)
                  }
              }
      
          }.toList()
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多