/
InjectorExt.kt
67 lines (53 loc) · 2.69 KB
/
InjectorExt.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package kuick.di
import com.google.inject.*
import kotlinx.coroutines.*
import kuick.core.*
import kuick.utils.*
import kotlin.coroutines.*
fun Guice(callback: Binder.() -> Unit): Injector = Guice.createInjector(object : Module {
override fun configure(binder: Binder) = callback(binder)
})
val Binder.registeredModules by WeakProperty { LinkedHashSet<Module>() }
abstract class GuiceModule(vararg val dependencies: Module) : Module {
abstract fun Binder.registerBindings()
final override fun configure(binder: Binder) {
// Only register this module if not registered previously
if (!binder.registeredModules.contains(this)) {
binder.registeredModules += this
// Register dependencies
for (dependency in dependencies) dependency.configure(binder)
binder.registerBindings()
}
}
}
fun GuiceModule(vararg dependencies: Module, callback: Binder.() -> Unit) = object : GuiceModule(*dependencies) {
override fun Binder.registerBindings() = callback()
}
inline fun Binder.bind(module: Module): Binder = this.apply { module.configure(this) }
inline fun <reified T> Binder.bind(instance: T): Binder = this.apply {
bind(T::class.java).toInstance(instance)
}
inline fun <reified T, reified R : T> Binder.bind(): Binder = this.apply {
bind(T::class.java).to(R::class.java)
}
inline fun <reified T> Binder.bindSelf(): Binder = this.apply {
bind(T::class.java).asEagerSingleton()
}
class InjectorNotInContextException : RuntimeException("Injector not in context")
class InjectorContext(val injector: Injector) : AbstractCoroutineContextElement(Key) {
companion object Key : CoroutineContext.Key<InjectorContext>
}
@KuickInternal
suspend fun injector(): Injector = coroutineContext[InjectorContext]?.injector ?: throw InjectorNotInContextException()
inline fun <reified T : Any> Injector.get() = this.getInstance(T::class.java)
inline fun <reified T : Any> Injector.get(callback: T.() -> Unit) = this.getInstance(T::class.java).apply(callback)
inline fun <reified T : Any> Injector.getOrNull() = try {
get<T>()
} catch (e: Throwable) {
null
}
suspend fun <T> withInjectorContextNoIntercepted(injector: Injector, callback: suspend CoroutineScope.() -> T): T =
withContext(InjectorContext(injector)) { callback() }
suspend fun <T> withInjectorContextIntercepted(injector: Injector, callback: suspend CoroutineScope.() -> T) = injector.runWithInjector { callback(CoroutineScope(coroutineContext)) }
@Deprecated("", ReplaceWith("withInjectorContextIntercepted(injector, callback)"))
suspend fun <T> withInjectorContext(injector: Injector, callback: suspend CoroutineScope.() -> T) = withInjectorContextIntercepted(injector, callback)