Ну, это выполнимо:
Сначала давайте определим службу и реализацию:
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()
}
Теперь у меня к вам вопрос: зачем вам это нужно?