Kotlin中具有通用类型参数的简单服务定位器

时间:2019-02-05 16:33:45

标签: design-patterns kotlin inversion-of-control service-locator

我跟随these instructions创建了一个简单的服务定位器,该定位器适用于Kotlin,并针对我的问题进行了简化:

object ServiceLocator {

    @JvmStatic
    fun getService(serviceName: String): Any {
        val service = lookupService(serviceName)

        if (service != null) {
            return service
        }

        throw UnknownServiceException()
    }

    private fun lookupService(serviceName: String): Any? {
        if (serviceName.equals("MyService")) {
            return MyService()
        }

        return null
    }
}

我可以如下使用它:

val myService = ServiceLocator.getService("MyService") as IMyService

我遇到的问题是myService的类型为Any。如果getService返回实际类型,我会更喜欢。理想情况下,我想这样使用它:

val myService = ServiceLocator.getService<IMyService>()

或者,如果不可能的话,可以这样做:

val myService = ServiceLocator.getService(IMyService::class)

我不知道如何使通用类型参数起作用。这是我尝试过的:

@JvmStatic
fun <T> getService(): T {
    val service = lookupService<T>()

    if (service != null) {
        return service
    }

    throw UnknownServiceException()
}

private fun <T> lookupService(): T? {
    if (T::class == IMyService::class) {
        return MyService()
    }

    return null
}

编译器抱怨两件事:

  1. T::class上,它抱怨“不能使用'T'作为化类型参数。请改用类。”
  2. return MyService()上,显示“类型不匹配。是否要求:T?找到了:MyService”

1 个答案:

答案 0 :(得分:2)

要在运行时访问类型T,而不必传入类(例如ServiceLocator.getService(IMyService::class)),则必须使用reified type parameter。暗示这意味着您必须将方法更改为inline functions。这样,您可以将代码更新为以下内容:

@JvmStatic
inline fun <reified T> getService(): T {
    val service = lookupService<T>()

    if (service != null) {
        return service
    }

    throw UnknownServiceException()
}

inline fun <reified T> lookupService(): T? {
    if (T::class == IMyService::class) {
        return MyService() as T
    }

    return null
}