main.Kontainer.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kontainer Show documentation
Show all versions of kontainer Show documentation
"Kotlin Depdency Injection Framework"
package de.peekandpoke.ultra.kontainer
import de.peekandpoke.ultra.common.Lookup
import kotlin.reflect.KClass
/**
* The container
*/
@Suppress("Detekt.TooManyFunctions")
class Kontainer internal constructor(
private val factory: ServiceProviderFactory,
) : KontainerAware {
/**
* Tools for debugging the kontainer and more
*/
val tools: KontainerTools = KontainerTools(this)
/**
* The blueprint for this kontainer
*/
val blueprint: KontainerBlueprint = factory.blueprint
/**
* Implementing [KontainerAware]
*/
override val kontainer: Kontainer = this
/**
* The root context is used, when services are directly requested from the Kontainer
*/
private val rootContext: InjectionContext = InjectionContext.kontainerRoot
/**
* Get the underlying [ServiceProviderFactory].
*/
fun getServiceProviderFactory(): ServiceProviderFactory = factory
// Cloning the kontainer ///////////////////////////////////////////////////////////////////////////////////////////
/**
* Create a new fresh instance of this [Kontainer].
*
* This will reset all dynamic services, just like creating a new kontainer from a [KontainerBlueprint].
*/
fun clone(): Kontainer = factory.newKontainer()
// getting services ////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Get all service classes that would satisfy the given [cls]
*/
fun getCandidates(cls: KClass): Set> = blueprint.superTypeLookup.getAllCandidatesFor(cls)
/**
* Get a service for the given class
*/
inline fun get() = get(T::class)
/**
* Get a service for the given class
*/
fun get(cls: KClass): T = get(cls, rootContext)
/**
* Get a service for the given [cls] or null if no service can be provided
*/
fun getOrNull(cls: KClass): T? = getOrNull(cls, rootContext)
/**
* Get a service for the given [cls], and when it is present run the [block] on it.
*
* When the service is not present null is returned.
* Otherwise, the result of the [block] is returned.
*/
inline fun use(cls: KClass, block: T.() -> R?): R? {
val type = blueprint.superTypeLookup.getDistinctForOrNull(cls) ?: return null
return get(type).block()
}
/**
* Get all services that are a super type of the given class
*/
fun getAll(cls: KClass): List = getAll(cls, rootContext)
/**
* Get all services that are a super type of the given class as a [Lookup]
*/
fun getLookup(cls: KClass): LazyServiceLookup = getLookup(cls, rootContext)
/**
* Get a provider for the given service class
*/
inline fun getProvider(): ServiceProvider = getProvider(T::class)
/**
* Get a provider for the given service class
*/
fun getProvider(cls: KClass): ServiceProvider {
val type = blueprint.superTypeLookup.getDistinctFor(cls)
return factory.getProvider(type)
}
// getting parameters //////////////////////////////////////////////////////////////////////////////////////////////
/**
* Check if there is a config value with the given [id] that is of the given [type]
*/
fun hasConfig(id: String, type: KClass<*>): Boolean {
return blueprint.configValues[id].let { it != null && it::class == type }
}
/**
* Get a config value by its [id]
*/
@Suppress("UNCHECKED_CAST")
fun getConfig(id: String): T = blueprint.configValues[id] as T
// internal helpers ////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Internally gets a [service] for the given [context]
*/
internal fun get(service: KClass, context: InjectionContext): T {
@Suppress("UNCHECKED_CAST")
return getProvider(service).provide(this, context) as T
}
/**
* Internally gets a [service] or null for the given [context]
*/
internal fun getOrNull(service: KClass, context: InjectionContext): T? {
val type = blueprint.superTypeLookup.getDistinctForOrNull(service) ?: return null
return get(type, context)
}
/**
* Internally gets all super type services of [cls] as a [List]
*/
internal fun getAll(cls: KClass, context: InjectionContext): List {
@Suppress("UNCHECKED_CAST")
return blueprint.superTypeLookup.getAllCandidatesFor(cls).map { get(it, context) as T }
}
/**
* Internally gets all super type services of [cls] as a [Lookup]
*/
internal fun getLookup(cls: KClass, context: InjectionContext): LazyServiceLookup {
@Suppress("UNCHECKED_CAST")
return blueprint.superTypeLookup.getLookupBlueprint(cls).with(this, context) as LazyServiceLookup
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy