diff options
author | Linnea Gräf <nea@nea.moe> | 2024-12-06 19:27:07 +0100 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2024-12-06 19:28:23 +0100 |
commit | f7507f384459b57460af899bf9ceae4f52f1ea21 (patch) | |
tree | 410d70c0a35de852278b03ac9243080d7e0a0490 /src/main/kotlin/moe/nea/ledger/utils/DI.kt | |
parent | 2c9132d0c755964800b710ce43c8feebd44f1299 (diff) | |
download | LocalTransactionLedger-f7507f384459b57460af899bf9ceae4f52f1ea21.tar.gz LocalTransactionLedger-f7507f384459b57460af899bf9ceae4f52f1ea21.tar.bz2 LocalTransactionLedger-f7507f384459b57460af899bf9ceae4f52f1ea21.zip |
refactor: Add DI and packages
Diffstat (limited to 'src/main/kotlin/moe/nea/ledger/utils/DI.kt')
-rw-r--r-- | src/main/kotlin/moe/nea/ledger/utils/DI.kt | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/main/kotlin/moe/nea/ledger/utils/DI.kt b/src/main/kotlin/moe/nea/ledger/utils/DI.kt new file mode 100644 index 0000000..1114127 --- /dev/null +++ b/src/main/kotlin/moe/nea/ledger/utils/DI.kt @@ -0,0 +1,63 @@ +package moe.nea.ledger.utils + +import java.lang.reflect.AnnotatedElement +import java.util.Collections +import java.util.Stack + +@Suppress("UNCHECKED_CAST") +class DI { + private fun <T : Any, C> internalProvide(type: Class<T>, element: AnnotatedElement? = null): T { + val provider = providers[type] as BaseDIProvider<T, C> + val context = if (element == null) provider.createEmptyContext() else provider.createContext(element) + val key = Pair(type, context) + val existingValue = values[key] + if (existingValue != null) return existingValue as T + if (type in injectionStack) { + error("Found injection cycle: ${injectionStack.joinToString(" -> ")} -> $type") + } + injectionStack.push(type) + val value = try { + provider.provideWithContext(this, context) + } catch (ex: Exception) { + throw RuntimeException("Could not create instance for type $type", ex) + } + val cycleCheckCookie = injectionStack.pop() + require(cycleCheckCookie == type) { "Unbalanced stack cookie: $cycleCheckCookie != $type" } + values[key] = value + return value + } + + fun <T : Any> provide(type: Class<T>, element: AnnotatedElement? = null): T { + return internalProvide<T, Any>(type, element) + } + + fun <T : Any> register(type: Class<T>, provider: BaseDIProvider<T, *>) { + providers[type] = provider + } + + fun registerInjectableClasses(vararg type: Class<*>) { + type.forEach { internalRegisterInjectableClass(it) } + } + + private fun <T : Any> internalRegisterInjectableClass(type: Class<T>) { + register(type, DIProvider.fromInjectableClass(type)) + } + + fun instantiateAll() { + providers.keys.forEach { + provide(it, null) + } + } + + fun getAllInstances(): Collection<Any> = + Collections.unmodifiableCollection(values.values) + + fun <T : Any> registerSingleton(value: T) { + register(value.javaClass, DIProvider.singeleton(value)) + } + + private val injectionStack: Stack<Class<*>> = Stack() + private val values = mutableMapOf<Pair<Class<*>, *>, Any>() + private val providers = mutableMapOf<Class<*>, BaseDIProvider<*, *>>() + +}
\ No newline at end of file |