Injector.kt

  1. package com.hexagontk.injection

  2. import kotlin.reflect.KClass

  3. /**
  4.  * Inject type instances based on the suppliers defined in the [Module].
  5.  */
  6. class Injector(private val module: Module = Module()) {

  7.     /**
  8.      * Inject an instance of the type class and the supplied tag. If the injector's module doesn't
  9.      * have a matching binding, then `null` is returned.
  10.      *
  11.      * @param T Generic type of the instance that will be created.
  12.      * @param type Class for the instance to create (class of T).
  13.      * @param tag Tag used to search the binding in the [Module].
  14.      * @return An instance of T or `null` if no binding for that type with the passed tag is found.
  15.      */
  16.     @Suppress("UNCHECKED_CAST") // bind operation takes care of type matching
  17.     fun <T : Any> injectOrNull(type: KClass<T>, tag: Any): T? =
  18.         module.bindings[Target(type, tag)]?.provide() as? T

  19.     @Suppress("UNCHECKED_CAST") // bind operation takes care of type matching
  20.     fun <T : Any> injectList(type: KClass<T>): List<T> =
  21.         module.bindings
  22.             .filter { it.key.type == type }
  23.             .map { it.value.provide() as T }

  24.     @Suppress("UNCHECKED_CAST") // bind operation takes care of type matching
  25.     fun <T : Any> injectMap(type: KClass<T>): Map<Any, T> =
  26.         module.bindings
  27.             .filter { it.key.type == type }
  28.             .map { it.key.tag to it.value.provide() as T }
  29.             .associate { it.first to it.second }

  30.     fun <T : Any> inject(type: KClass<T>, tag: Any): T =
  31.         injectOrNull(type, tag) ?: error("${type.java.name} generator missing")

  32.     fun <T : Any> inject(type: KClass<T>): T =
  33.         inject(type, Unit)

  34.     fun <T : Any> injectOrNull(type: KClass<T>): T? =
  35.         injectOrNull(type, Unit)

  36.     inline fun <reified T : Any> inject(tag: Any): T =
  37.         inject(T::class, tag)

  38.     inline fun <reified T : Any> inject(): T =
  39.         inject(T::class)

  40.     inline fun <reified T : Any> injectOrNull(tag: Any): T? =
  41.         injectOrNull(T::class, tag)

  42.     inline fun <reified T : Any> injectOrNull(): T? =
  43.         injectOrNull(T::class)

  44.     inline fun <reified T : Any> injectList(): List<T> =
  45.         injectList(T::class)

  46.     inline fun <reified T : Any> injectMap(): Map<Any, T> =
  47.         injectMap(T::class)
  48. }