Multibinders don't have a way to bind a default empty set #261
Comments
I like this approach best:
It's especially nice 'cause we also want to support returning multiple values for other scenarios. |
I like the |
As cgruber mentioned: 'default bindings' and overrides= are both incarnations of the same concept - defining the precedence of duplicated bindings. Having said that it is natural to me to name both of them using the same wording. It might seem a small change but this way it won't increase conceptual weight of the framework. There's already override concept at the modules level so it is easy to understand what it means when applied to Provides binding (lower level). Last thing that I'm not 100% sure but that is obvious to my symmetry seeking brain is the fact that when we would have Note a third option (which I don't like but mentioning for completeness of discussion). |
submitted a PR for this, as particularly adding this takes out some ugly workarounds wrt default to empty set. |
any chance we can get dagger 1.1 released? I'm starting to get support email which could be avoided if I can switch to SET_VALUES.. |
I'm going to try to today. Friday got away from me. Jake Wharton On Mon, Aug 5, 2013 at 8:05 AM, Adrian Cole notifications@github.comwrote:
|
I'm going to close this, as it is closed by #291. |
When subcomponent simple names conflict, prepend the enclosing types (and then package levels) until a unique simple name is generated. This fixes Github issues square#194, square#236, and square#261. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=108989611
Problem
If someone makes a contribution to a set via
then someone can do this
... and all is well. But what if someone wants to inject a set of Foos, where it is not clear whether or not someone will actually bind any Foos. An example would be ServiceManager from Guava. It takes a
Set<Service>
, and this will fail if it is not present, but there is no way to guarantee that the empty set is to be made available even if nothing is bound.Guice approach
Guice allows the declaration of the binding, with no contents because the way bindings are registered requires the creation of the set binding first, before additional contributions are made. Dagger simply declares the contributions and implicitly creates the Set.
Possible Solutions
Default Bindings
This is something @swankjesse and I talked about a long time ago - a sort of "default binding." That is, if there is nothing else bound in its place, use this. This would work similarly to how overrides= works in a way, except that it's at the binding level, and the default is a normal binding. But it's a way of providing a precedence order for a select number of duplicate bindings. The precedence woudl naturally be bindings in overrides= modules beats other bindings, and normal bindings beat default bindings.
Note, with this, multiple unique bindings at a given level (two defaults, or two normals, etc.) would be prohibited. This would need to be rationalized with the multibinder infrastructure to ensure that an
@Provides(useByDefault=true, type=UNIQUE) Set<Foo> ...
could be properly unseated by one or more@Provides(type=SET) Foo ...
bindings.If we did this, we'd also want to make sure we have a decent visual representation for this in the .dot writer.
Advantage: Multibinder declaration is still type-rich (Set<Foo<Bar>>)
Multiple value muiltibinders.
This would provide some way to contribute zero or more values to the set of a multibinder, but one would contribute zero values. Some (possibly quite horrible) example might be
This would contribute all values of Set to the SetBinder for Set. However, one could return an empty Set. The SetBinding for Set would then be bound, and just happen to have no elements if nothing else was bound.
Advantage: Allows multiple values to be provided by a single module, computed late.
Signal for the presence of a multibinder (possibly useful for other declarations)
A signal would be made for noting the presence of a multibinder. This could be an annotation on the module
Here, this mirrors a binding, but simply declares the binding, with no contents.
Conclusion
One way or another, we need to address the default binding problem, at least for multibinders. THe three options above are actually not mutually exclusive, as they have other possible reasons for existing than declaring a multibinder for graph completeness, but they each could solve this particular problem.
My own preference is a default bindings approach. It deals with a case where people in Guice have used Optional-Injection, is a healthy (I think) way to address the use of Dagger in the context of plugin infrastructures, and lets the graph be managed flexibly.
The text was updated successfully, but these errors were encountered: