I am using Google's MapBinders to map an Event Listener (my own Custom interface) to an EventType.
MapBinder<EventType, EventListener> eventEventHandlerMapBinder =
MapBinder.newMapBinder(binder(), EventType.class, EventListener.class);
eventEventHandlerMapBinder
.addBinding(EventType.DUMMY_EVENT)
.to(DummyListener.class);
This lets me inject Map<EventType, Provider<EventListener>> eventEventHandlerMapBinder
into my EventRegistry or wherever.
I now want to map multiple EventListeners to one Event Type, i.e. for DUMMY_EVENT, I want DummyListener.class and AnotherDummyListener.class to be bound. How do I do that?
I cannot do this, because MapBinder creates a Provider for the V:
MapBinder<EventType, List> eventEventHandlerMapBinder2 =
MapBinder.newMapBinder(binder(), EventType.class, List.class);
eventEventHandlerMapBinder2
.addBinding(EventType.DUMMY_EVENT)
.to((Key<? extends List>) Arrays.asList(DummyListener.class, AnotherDummyListener.class));
CodePudding user response:
You can use a combination of MapBinder
and Multibinder
(but you would need to switch from List
to Set
, but I guess it shouldn't be an issue).
Here is a working simple example:
interface Service {
}
static class Service1 implements Service {
}
static class Service2 implements Service {
}
public static void main(String[] args) {
var injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
var multibinder = Multibinder.newSetBinder(binder(), Service.class);
multibinder.addBinding().to(Service1.class);
multibinder.addBinding().to(Service2.class);
var mapBinder = MapBinder.newMapBinder(binder(), new TypeLiteral<String>() {}, new TypeLiteral<Set<Service>>() {});
mapBinder.addBinding("foo").to(Key.get(new TypeLiteral<Set<Service>>(){}));
}
});
var map = injector.getInstance(Key.get(new TypeLiteral<Map<String, Set<Service>>>() {
}));
assert map.get("foo") != null;
}
To distinguish between different Set
s, you can use annotations, such as @Named
/Names
or use custom ones.