aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt')
-rw-r--r--src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt b/src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt
new file mode 100644
index 0000000..b5ce550
--- /dev/null
+++ b/src/main/kotlin/moe/nea/ledger/utils/di/DIProvider.kt
@@ -0,0 +1,51 @@
+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>
+ 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
+}