Multi-binding

Kodein-DI allows multi bindings via a binding set.

In a Set

Binding in a Set

To have multiple bindings in a set, you need to:

  • Declare that you are using a set binding for a particular bound type.

  • Add bindings to the set.

Example creating a set of Configuration bindings.
val di = DI {
    bindSet<Configuration>() (1)

    inSet<Configuration> { provider { FooConfiguration() } } (2)
    inSet<Configuration> { singleton { BarConfiguration() } } (2)
}
1 Creating a set binding of Configuration.
2 Binding multiple Configuration implementations.

You can:

  • Use different binding types (such as provider or singleton) in the same set.

  • Add bindings to the same set in different modules, provided that the set has been declared first.

You can also bind multiple bindings with arguments (such as factory or multiton) in a set as long as all bindings share the same argument type.

Example creating a set of Result bindings.
val di = DI {
    bindArgSet<Query, Result>() (1)

    inSet<Result> { factory { q: Query -> Foo.query(q) } } (2)
    inSet<Result> { multiton { q: Query -> Bar.query(q) } } (2)
}
1 Creating an argument set binding of Result for arguments of type Query.
2 Binding multiple Result factories implementations.

Retrieving from a Set

Note that the type being bound is Set<T>, not T.
Therefore, you need to retrieve a Set:

Example retrieving set of Configuration.
val configurations: Set<Configuration> by di.instance()

To retrieve a Set with argument, thus going through a factory or a multiton, you need to pass the needed argument to the instance function.

Example retrieving set of Result with Query argument.
val result: Set<Result> by di.instance(arg = Query("SELECT * FROM USER;"))

In a map

Kodein-DI does not directly support map multi-binding. However, it is very easy to create a binding map by using a binding set.

First, create the following primitive:

Example of the type alias for a map multi-binding as Map<String, Configuration>.
typealias ConfigurationEntry = Pair<String, Configuration>
typealias ConfigurationEntries = Set<ConfigurationEntry>

Then, bind with keys:

Example binding as in a map multibinding.
val di = DI {
    bindSet<ConfigurationEntry>()

    inSet<ConfigurationEntry> { singleton { "foo" to FooConfiguration() } }
    inSet<ConfigurationEntry> { provider { "bar" to BarConfiguration() } }
}

Finally, retrieve the map:

Example retrieving a map multibinding.
val configurations by di.instance<ConfigurationEntries>().toMap()