K2: Add ability identify DI components by string key instead of KClass
It allows having several the same typed-component in the container
This commit is contained in:
committed by
Space Team
parent
58c1b5dd1f
commit
dab50daf56
@@ -24,6 +24,10 @@ abstract class FirSession @PrivateSessionConstructor constructor(
|
|||||||
return generateAccessor(T::class)
|
return generateAccessor(T::class)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : FirSessionComponent> sessionComponentAccessor(id: String): ArrayMapAccessor<FirSessionComponent, FirSessionComponent, T> {
|
||||||
|
return generateAccessor(id)
|
||||||
|
}
|
||||||
|
|
||||||
inline fun <reified T : FirSessionComponent> nullableSessionComponentAccessor(): NullableArrayMapAccessor<FirSessionComponent, FirSessionComponent, T> {
|
inline fun <reified T : FirSessionComponent> nullableSessionComponentAccessor(): NullableArrayMapAccessor<FirSessionComponent, FirSessionComponent, T> {
|
||||||
return generateNullableAccessor(T::class)
|
return generateNullableAccessor(T::class)
|
||||||
}
|
}
|
||||||
@@ -38,6 +42,11 @@ abstract class FirSession @PrivateSessionConstructor constructor(
|
|||||||
registerComponent(tClass, value)
|
registerComponent(tClass, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SessionConfiguration
|
||||||
|
fun register(keyQualifiedName: String, value: FirSessionComponent) {
|
||||||
|
registerComponent(keyQualifiedName, value)
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
val moduleData = nullableModuleData ?: return "Libraries session"
|
val moduleData = nullableModuleData ?: return "Libraries session"
|
||||||
return "Source session for module ${moduleData.name}"
|
return "Source session for module ${moduleData.name}"
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
|
|||||||
protected abstract val typeRegistry: TypeRegistry<K, V>
|
protected abstract val typeRegistry: TypeRegistry<K, V>
|
||||||
|
|
||||||
abstract class AbstractArrayMapAccessor<K : Any, V : Any, T : V>(
|
abstract class AbstractArrayMapAccessor<K : Any, V : Any, T : V>(
|
||||||
protected val key: KClass<out K>,
|
|
||||||
protected val id: Int
|
protected val id: Int
|
||||||
) {
|
) {
|
||||||
protected fun extractValue(thisRef: AbstractArrayMapOwner<K, V>): T? {
|
protected fun extractValue(thisRef: AbstractArrayMapOwner<K, V>): T? {
|
||||||
@@ -28,7 +27,11 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun registerComponent(tClass: KClass<out K>, value: V)
|
protected abstract fun registerComponent(keyQualifiedName: String, value: V)
|
||||||
|
|
||||||
|
protected fun registerComponent(tClass: KClass<out K>, value: V) {
|
||||||
|
registerComponent(tClass.qualifiedName!!, value)
|
||||||
|
}
|
||||||
|
|
||||||
final override fun iterator(): Iterator<V> = arrayMap.iterator()
|
final override fun iterator(): Iterator<V> = arrayMap.iterator()
|
||||||
|
|
||||||
@@ -40,21 +43,20 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ArrayMapAccessor<K : Any, V : Any, T : V>(
|
class ArrayMapAccessor<K : Any, V : Any, T : V>(
|
||||||
key: KClass<out K>,
|
private val keyQualifiedName: String,
|
||||||
id: Int,
|
id: Int,
|
||||||
val default: T? = null
|
val default: T? = null
|
||||||
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(key, id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V> {
|
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V> {
|
||||||
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T {
|
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T {
|
||||||
return extractValue(thisRef)
|
return extractValue(thisRef)
|
||||||
?: default
|
?: default
|
||||||
?: error("No '$key'($id) in array owner: $thisRef")
|
?: error("No '$keyQualifiedName'($id) in array owner: $thisRef")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NullableArrayMapAccessor<K : Any, V : Any, T : V>(
|
class NullableArrayMapAccessor<K : Any, V : Any, T : V>(
|
||||||
key: KClass<out K>,
|
|
||||||
id: Int
|
id: Int
|
||||||
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(key, id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V?> {
|
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V?> {
|
||||||
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T? {
|
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T? {
|
||||||
return extractValue(thisRef)
|
return extractValue(thisRef)
|
||||||
}
|
}
|
||||||
@@ -65,19 +67,27 @@ abstract class TypeRegistry<K : Any, V : Any> {
|
|||||||
private val idCounter = AtomicInteger(0)
|
private val idCounter = AtomicInteger(0)
|
||||||
|
|
||||||
fun <T : V, KK : K> generateAccessor(kClass: KClass<KK>, default: T? = null): ArrayMapAccessor<K, V, T> {
|
fun <T : V, KK : K> generateAccessor(kClass: KClass<KK>, default: T? = null): ArrayMapAccessor<K, V, T> {
|
||||||
return ArrayMapAccessor(kClass, getId(kClass), default)
|
return ArrayMapAccessor(kClass.qualifiedName!!, getId(kClass), default)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : V> generateAccessor(keyQualifiedName: String, default: T? = null): ArrayMapAccessor<K, V, T> {
|
||||||
|
return ArrayMapAccessor(keyQualifiedName, getId(keyQualifiedName), default)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : V, KK : K> generateNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, T> {
|
fun <T : V, KK : K> generateNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, T> {
|
||||||
return NullableArrayMapAccessor(kClass, getId(kClass))
|
return NullableArrayMapAccessor(getId(kClass))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <KK : K> generateAnyNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, *> {
|
fun <KK : K> generateAnyNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, *> {
|
||||||
return NullableArrayMapAccessor(kClass, getId(kClass))
|
return NullableArrayMapAccessor(getId(kClass))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : K> getId(kClass: KClass<T>): Int {
|
fun <T : K> getId(kClass: KClass<T>): Int {
|
||||||
return idPerType.customComputeIfAbsent(kClass.qualifiedName!!) { idCounter.getAndIncrement() }
|
return getId(kClass.qualifiedName!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getId(keyQualifiedName: String): Int {
|
||||||
|
return idPerType.customComputeIfAbsent(keyQualifiedName) { idCounter.getAndIncrement() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ abstract class AttributeArrayOwner<K : Any, T : Any> protected constructor(
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
constructor() : this(EmptyArrayMap as ArrayMap<T>)
|
constructor() : this(EmptyArrayMap as ArrayMap<T>)
|
||||||
|
|
||||||
final override fun registerComponent(tClass: KClass<out K>, value: T) {
|
final override fun registerComponent(keyQualifiedName: String, value: T) {
|
||||||
val id = typeRegistry.getId(tClass)
|
val id = typeRegistry.getId(keyQualifiedName)
|
||||||
when (arrayMap.size) {
|
when (arrayMap.size) {
|
||||||
0 -> {
|
0 -> {
|
||||||
arrayMap = OneElementArrayMap(value, id)
|
arrayMap = OneElementArrayMap(value, id)
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ abstract class ComponentArrayOwner<K : Any, V : Any> : AbstractArrayMapOwner<K,
|
|||||||
final override val arrayMap: ArrayMap<V> =
|
final override val arrayMap: ArrayMap<V> =
|
||||||
ArrayMapImpl()
|
ArrayMapImpl()
|
||||||
|
|
||||||
final override fun registerComponent(tClass: KClass<out K>, value: V) {
|
final override fun registerComponent(keyQualifiedName: String, value: V) {
|
||||||
val id = typeRegistry.getId(tClass)
|
val id = typeRegistry.getId(keyQualifiedName)
|
||||||
try {
|
try {
|
||||||
arrayMap[id] = value
|
arrayMap[id] = value
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw RuntimeException(createDiagnosticMessage(id, tClass), e)
|
throw RuntimeException(createDiagnosticMessage(id, keyQualifiedName), e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,10 +29,10 @@ abstract class ComponentArrayOwner<K : Any, V : Any> : AbstractArrayMapOwner<K,
|
|||||||
return arrayMap[id] ?: error("No '$key'($id) component in array: $this")
|
return arrayMap[id] ?: error("No '$key'($id) component in array: $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createDiagnosticMessage(id: Int, tClass: KClass<*>): String = buildString {
|
private fun createDiagnosticMessage(id: Int, keyQualifiedName: String): String = buildString {
|
||||||
appendLine("Error occurred during registration of component in array")
|
appendLine("Error occurred during registration of component in array")
|
||||||
appendLine("Currently registered")
|
appendLine("Currently registered")
|
||||||
appendLine(" $id: $tClass")
|
appendLine(" $id: $keyQualifiedName")
|
||||||
appendLine("Registrar:")
|
appendLine("Registrar:")
|
||||||
for ((kClass, x) in typeRegistry.allValuesThreadUnsafeForRendering()) {
|
for ((kClass, x) in typeRegistry.allValuesThreadUnsafeForRendering()) {
|
||||||
appendLine(" $x: $kClass")
|
appendLine(" $x: $kClass")
|
||||||
|
|||||||
Reference in New Issue
Block a user