Module.kt

  1. package com.hexagontk.injection

  2. import com.hexagontk.injection.Provider.Generator
  3. import com.hexagontk.injection.Provider.Instance
  4. import kotlin.reflect.KClass

  5. /**
  6.  * Set of bindings from types with tags to instances' generators.
  7.  */
  8. class Module {

  9.     internal var bindings: Map<Target<out Any>, Provider<Any>> = emptyMap()

  10.     fun clear() {
  11.         bindings = emptyMap()
  12.     }

  13.     fun <T : Any> bind(type: KClass<T>, providers: Map<Any, Provider<T>>) {
  14.         providers.forEach { (k, v) -> bind(Target(type, k), v) }
  15.     }

  16.     fun <T : Any> bind(type: KClass<T>, providers: List<Provider<T>>) {
  17.         providers.forEachIndexed { ii, it -> bind(Target(type, ii), it) }
  18.     }

  19.     fun <T : Any> bind(target: Target<T>, provider: Provider<T>) {
  20.         val binding = target.toString()

  21.         check(!bindings.containsKey(target)) {
  22.             "$binding already bound. Override only allowed in tests (using `forceBind`)"
  23.         }

  24.         bindings = bindings + (target to provider)
  25.     }

  26.     inline fun <reified T : Any> bind(instance: T) {
  27.         bind(Target(T::class), Instance(instance))
  28.     }

  29.     inline fun <reified T : Any> bind(noinline generator: () -> T) {
  30.         bind(Target(T::class), Generator(generator))
  31.     }

  32.     inline fun <reified T : Any> bind(tag: Any, instance: T) {
  33.         bind(Target(T::class, tag), Instance(instance))
  34.     }

  35.     inline fun <reified T : Any> bind(tag: Any, noinline generator: () -> T) {
  36.         bind(Target(T::class, tag), Generator(generator))
  37.     }

  38.     inline fun <reified T : Any> bindInstances(instances: Map<Any, T>) {
  39.         bind(T::class, instances.mapValues { Instance(it.value) })
  40.     }

  41.     inline fun <reified T : Any> bindInstances(instances: List<T>) {
  42.         bind(T::class, instances.map { Instance(it) })
  43.     }

  44.     inline fun <reified T : Any> bindInstances(vararg instances: Pair<Any, T>) {
  45.         bindInstances(instances.associate { (k, v) -> k to v })
  46.     }

  47.     inline fun <reified T : Any> bindInstances(vararg instances: T) {
  48.         bindInstances(instances.map { it })
  49.     }

  50.     inline fun <reified T : Any> bindGenerators(generators: Map<Any, () -> T>) {
  51.         bind(T::class, generators.mapValues { Generator(it.value) })
  52.     }

  53.     inline fun <reified T : Any> bindGenerators(generators: List<() -> T>) {
  54.         bind(T::class, generators.map { Generator(it) })
  55.     }

  56.     inline fun <reified T : Any> bindGenerators(vararg generators: Pair<Any, () -> T>) {
  57.         bindGenerators(generators.toMap())
  58.     }

  59.     inline fun <reified T : Any> bindGenerators(vararg generators: () -> T) {
  60.         bindGenerators(generators.map { it })
  61.     }

  62.     override fun toString(): String =
  63.         bindings
  64.             .map { it.key }
  65.             .map { it.type.java.name to if (it.tag is Unit) "" else " (${it.tag})"}
  66.             .joinToString("\n", "Bound classes with parameters:\n") {
  67.                 "\t * ${it.first}${it.second}"
  68.             }
  69. }