evant / kotlin-inject

Dependency injection lib for kotlin
Apache License 2.0
1.29k stars 58 forks source link

Better handle empty multiple bindings. #249

Open evant opened 1 year ago

evant commented 1 year ago

You may want to declare a multi-binding but provide no values. This is useful for cases where you want to 'extend' the set provided. Right now this is not possible because you have to declare at least one @IntoMap or @IntoSet in order for it to not complain that it can't provide the value. Dagger has 2 ways around this:

Add @Multibinds to the provider

@Multibinds abstract fun aSet(): Set<Foo>

Provide an empty collection with @ElementsIntoSet

@Provides @ElementsIntoSet
fun primeEmptyFooSet(): Set<Foo> = emptySet()
evant commented 1 year ago

I'm personally not a fan of having 2 different ways to do the same thing. I'm leaning towards only providing the second as it can be useful in it's own right to group a bunch of multi-binds together into a single method. A way we could do this is with an option to the @IntoSet and @IntoMap annotations to control it's return type. Ex:

@Provides @IntoSet(multiple=true) fun defaultSet(): Set<Foo> = setOf(Foo("one"), Foo("two"))
@Provides @IntoMap(multiple=true) fun defaultMap(): Map<String, Foo> = mapOf("one" to Foo1(), "two" to Foo2())
dave08 commented 1 year ago

Then it wouldn't be just usable as a default empty set provider, but rather a way to provide multiple Foo per @Provides @IntoSet(multiple=true) function? There could potentially be more than one of those and they'll be unioned?

evant commented 1 year ago

Yep, exactly

rharter commented 1 year ago

Is there a particular preference for overloading @Into[Set|Map] vs. having a separate @ElementsInto... annotation? I agree with having a single approach, but FWIW I prefer the latter approach since it's a bit more explicit and seems harder to forget to override a property.

evant commented 11 months ago

It felt simpler in the moment, but I'm not particularly attached to it, will think about it when implementing. Note that @IntoMap will yell at you if you get it wrong because it expects the return to be a Pair, @IntoSet would not, unfortunately since a set of sets is technically valid.