Cookbook

Inner Classes and Path-Dependent Types

To instantiate path-dependent types via constructor, their prefix type has to be present in DI object graph:

import distage._

trait Path {
  class A
  class B
}

val path = new Path {}
// path: AnyRef with Path = repl.Session$App0$$anon$1@421fb4d5

val module = new ModuleDef {
  make[path.A]
  make[path.type].from[path.type](path: path.type)
}
// module: AnyRef with ModuleDef = Set(SingletonBinding({type.repl.Session.App0.<refinement>.type},InstanceImpl(repl.Session.App0.<refinement>.type,repl.Session$App0$$anon$1@421fb4d5),Set(<*>, <singleton>),(cookbook.md:25)), SingletonBinding({type.repl.Session.App0.path.A},TypeImpl(repl.Session.App0.path.A),Set(<*>, <singleton>),(cookbook.md:24)))

The same applies to type projections:

val module1 = new ModuleDef {
  make[Path#B]
  make[Path].from(new Path {})
}
// module1: AnyRef with ModuleDef = Set(SingletonBinding({type.repl.Session.App0.Path},InstanceImpl(repl.Session.App0.Path,repl.Session$App0$$anon$3$$anon$4@ec693c),Set(<*>, <singleton>),(cookbook.md:34)), SingletonBinding({type.repl.Session.App0.Path#B},TypeImpl(repl.Session.App0.Path#B),Set(<*>, <singleton>),(cookbook.md:33)))

Provider and instance bindings and also compile-time mode in distage-static module do not require the singleton type prefix to be present in DI object graph:

val module2 = new ModuleDef {
  make[Path#B].from {
    val path = new Path {}
    new path.B
  }
}
// module2: AnyRef with ModuleDef = Set(SingletonBinding({type.repl.Session.App0.Path#B},InstanceImpl(path.B,repl.Session$App0$Path$B@83f7b16),Set(<*>, <singleton>),(cookbook.md:42)))

Depending on Locator

Classes can depend on the Locator:

import distage._

class A(all: LocatorRef) {
  def c = all.get.get[C]
}
class B
class C

val module = new ModuleDef {
  make[A]
  make[B]
  make[C]
}

val locator = Injector().produce(module)

assert(locator.get[A].c eq locator.get[C]) 

It is recommended to avoid this if possible, doing so is often a sign of broken application design.