All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.org.kodein.di.bindings.BindingDI.kt Maven / Gradle / Ivy

There is a newer version: 7.22.0
Show newest version
package org.kodein.di.bindings

import org.kodein.di.*
import org.kodein.type.TypeToken


// /!\
// These classes should be generic but cannot be because the Kotlin's type inference engine cannot infer a function's receiver type from it's return type.
// Ie, this class can be generic if/when the following code becomes legal in Kotlin:
//
// class TestContext
// inline fun  testFactory(f: TestContext.(A) -> T): T = ...
// fun test() { /* bind() with */ testFactory { name: String -> "hello, $name!" } }

/**
 * Indicates that the context of a retrieval is accessible.
 *
 * @param C The type of the context
 */
public interface WithContext {
    /**
     * The context that was given at retrieval.
     */
    public val context: C
}

/**
 * Direct DI interface to be passed to factory methods that hold references.
 *
 * It is augmented to allow such methods to access the context of the retrieval, as well as a factory from the binding it is overriding (if it is overriding).
 *
 * @param C The type of the context
 */
@DI.DIDsl
public interface BindingDI : DirectDI, WithContext {

    /**
     * Gets a factory from the overridden binding.
     *
     * @return A factory yielded by the overridden binding.
     * @throws DI.NotFoundException if this binding does not override an existing binding.
     * @throws DI.DependencyLoopException When calling the factory function, if the instance construction triggered a dependency loop.
     */
    public fun overriddenFactory(): (Any?) -> Any

    /**
     * Gets a factory from the overridden binding, if this binding overrides an existing binding.
     *
     * @return A factory yielded by the overridden binding, or null if this binding does not override an existing binding.
     * @throws DI.DependencyLoopException When calling the factory function, if the instance construction triggered a dependency loop.
     */
    public fun overriddenFactoryOrNull(): ((Any?) -> Any)?

    public fun onErasedContext(): BindingDI
}

public object ErasedContext : DIContext {
    override val type: TypeToken get() = TypeToken.Any
    override val value: ErasedContext get() = ErasedContext
}

/**
 * Direct DI interface to be passed to provider methods that hold references.
 *
 * It is augmented to allow such methods to access the context of the retrieval, as well as a provider or instance from the binding it is overriding (if it is overriding).
 *
 * @param C The type of the context
 */
@DI.DIDsl
public interface NoArgBindingDI : DirectDI, WithContext {

    /**
     * Gets a provider from the overridden binding.
     *
     * @return A provider yielded by the overridden binding.
     * @throws DI.NotFoundException if this binding does not override an existing binding.
     * @throws DI.DependencyLoopException When calling the provider function, if the instance construction triggered a dependency loop.
     */
    public fun overriddenProvider(): () -> Any

    /**
     * Gets a provider from the overridden binding, if this binding overrides an existing binding.
     *
     * @return A provider yielded by the overridden binding, or null if this binding does not override an existing binding.
     * @throws DI.DependencyLoopException When calling the provider function, if the instance construction triggered a dependency loop.
     */
    public fun overriddenProviderOrNull(): (() -> Any)?

    /**
     * Gets an instance from the overridden binding.
     *
     * @return An instance yielded by the overridden binding.
     * @throws DI.NotFoundException if this binding does not override an existing binding.
     * @throws DI.DependencyLoopException If the instance construction triggered a dependency loop.
     */
    public fun overriddenInstance(): Any /*= overriddenProvider().invoke()*/

    /**
     * Gets an instance from the overridden binding, if this binding overrides an existing binding.
     *
     * @return An instance yielded by the overridden binding, or null if this binding does not override an existing binding.
     * @throws DI.DependencyLoopException If the instance construction triggered a dependency loop.
     */
    public fun overriddenInstanceOrNull(): Any? /*= overriddenProviderOrNull()?.invoke()*/
}

internal class NoArgBindingDIWrap(private val _di: BindingDI) : NoArgBindingDI, DirectDI by _di, WithContext by _di {
    override fun overriddenProvider() = _di.overriddenFactory().toProvider { Unit }
    override fun overriddenProviderOrNull() = _di.overriddenFactoryOrNull()?.toProvider { Unit }
    override fun overriddenInstance() = overriddenProvider().invoke()
    override fun overriddenInstanceOrNull() = overriddenProviderOrNull()?.invoke()
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy