There is an interface DCE, which is implemented by a class DCEImpl which has a dependency, say, string S, which it gets via its constructor.
The universe of S is limited, say S can only take values {'A','B','C'}.
There is an already existing Guice module that accepts the value of S in its constructor, and then binds the interface DCE to the correctly initialized version of DCEImpl.
public class DCEModule extends AbstractModule {
private final String s;
public DCEModule(String s){
this.s = s;
}
protected void configure() {
bind(DCE.class).toInstance(new DCEImpl(s));
}
}
Now I have a class C
which needs a List<DCE>
with all the 3 implementations (actually a lot more than 3, using 3 for example purpose).
I want to inject this list via Guice in C
. To do that, I created a new module DCEPModule
, which will provide a List<DCE>
in this way:
@Provides
List<DCE> getDCE() {
for(String s: S){
Module m = new DCEModule(s);
install(m);
Injector injector = Guice.createInjector(m);
listDomains.add(injector.getInstance(DCE.class));
}
}
My problem is that I don't want to call a new injector in this module, because DCEPModule
will be installed by a different module.
public class NewModule extends AbstractModule {
protected void configure() {
install(DCEPModule);
}
}
I want a way to get the List<DCE>
without explicitly creating a new injector in DCEPModule
.
You can achieve this by using a Multibinder
(javadoc, wiki).
Here’s an example:
public class SnacksModule extends AbstractModule {
protected void configure(){
Multibinder<Snack> multibinder = Multibinder.newSetBinder(binder(), Snack.class);
multibinder.addBinding().toInstance(new Twix());
multibinder.addBinding().toProvider(SnickersProvider.class);
multibinder.addBinding().to(Skittles.class);
}
}
Now, the multibinder will provide a Set<Snack>
. If you absolutely need a List
instead of a Set
, then you can add a method to your module like this:
@Provides
public List<Snack> getSnackList(Set<Snack> snackSet) {
return new ArrayList(snackSet);
}
You can add implementations to the same Multibinding in more than one module. When you call Multibinder.newSetBinder(binder, type)
it doesn’t necessarily create a new Multibinding. If a Multibinding already exists for for that type, then you will get the existing Multibinding.