Создать функцию, наследующую компонент koin - PullRequest
0 голосов
/ 08 октября 2019

Я пытаюсь упростить:

// Tag class with KoinComponent
class HelloApp : KoinComponent {

    // lazy inject dependency
    val helloService: HelloServiceImpl by inject()

    fun sayHello(){
        helloService.sayHello()
    }
}

до чего-то вроде

fun sayHello() = koinComponent {
    val helloService: HelloServiceImpl by inject()
    helloService.sayHello()
}

Возможно ли так, или я обречен на создание класса с invoke оператор?

1 Ответ

1 голос
/ 08 октября 2019

Ну, это выполнимо:

Сначала давайте определим службу и реализацию:

interface HelloService {
    fun sayHello()
}

class HelloServiceImpl(private val name: String) : HelloService {
    override fun sayHello() {
        println("Hello, $name!")
    }
}

Довольно очевидно, что служба скажет "Hello" человеку, настроенному в его конструкторе.

Теперь функция koinComponent:

fun <T> koinComponent(block: Koin.() -> T) {
    GlobalContext.get().koin.block()
}

Ваша функция:

fun sayHello() = koinComponent {
    val helloService: HelloServiceImpl by inject()

    helloService.sayHello()
}

И использование:

fun main() {
    startKoin {
        modules(listOf(
            module {
                single { HelloServiceImpl("majkrzak") }
            }
        ))
    }

    sayHello()
}

Вывод: Hello, majkrzak!

Все очень просто: чтобы использовать делегат inject , вам нужен контекст Koin. На самом деле, KoinComponent работает, используя GlobalContext:

interface KoinComponent {
    fun getKoin(): Koin = GlobalContext.get().koin
}

inline fun <reified T> KoinComponent.inject(
        qualifier: Qualifier? = null,
        noinline parameters: ParametersDefinition? = null
): Lazy<T> =
        getKoin().inject(qualifier, parameters)

Итак, почему бы не сделать то же самое? Мы объявляем функцию koinComponent, чтобы ее аргумент block вызывался с получателем Koin, и неявно используем этот глобальный экземпляр koin.

Мы можем сделать его более пригодным для повторного использования, используя значения по умолчанию:

fun <T> koinComponent(koin: Koin = GlobalContext.get().koin, block: Koin.() -> T) {
    koin.block()
}

Теперь у меня к вам вопрос: зачем вам это нужно?

...