blob: bd5b9efac4078b40ec31c02b1ffe094bdff11b42 (
plain)
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
|
package moe.nea.ledger.utils.di
import java.lang.reflect.AnnotatedElement
import java.lang.reflect.Constructor
fun interface DIProvider<T : Any> : BaseDIProvider<T, Unit> {
override fun provideWithContext(di: DI, context: Unit): T {
return provide(di)
}
override fun createContext(element: AnnotatedElement) {
}
override fun createEmptyContext() {
}
fun provide(di: DI): T
companion object {
fun <T : Any> fromInjectableClass(clazz: Class<T>): DIProvider<T> {
@Suppress("UNCHECKED_CAST")
val cons = (clazz.constructors.find { it.getAnnotation(Inject::class.java) != null }
?: clazz.constructors.find { it.parameterCount == 0 }
?: error("Could not find DI injection entrypoint for class $clazz"))
as Constructor<out T>
// TODO: consider using unsafe init to inject the parameters *before* calling the constructor
return DIProvider { di ->
val typArgs = cons.parameters.map {
di.provide(it.type, it)
}.toTypedArray()
val instance = cons.newInstance(*typArgs)
for (it in clazz.fields) {
if (it.getAnnotation(Inject::class.java) == null) continue
it.set(instance, di.provide(it.type, it))
}
instance
}
}
fun <T : Any> singeleton(value: T): DIProvider<T> {
return DIProvider { _ -> value }
}
}
}
interface BaseDIProvider<T : Any, C> {
fun createContext(element: AnnotatedElement): C
fun provideWithContext(di: DI, context: C): T
fun createEmptyContext(): C
}
|