tags:

views:

135

answers:

1

So according to my testing, If you have something like:

Module modA = new AbstractModule() {
    public void configure() {
        bind(A.class).to(AImpl.class);
        bind(C.class).to(ACImpl.class);
        bind(E.class).to(EImpl.class);
    }
}

Module modB = New AbstractModule() {
    public void configure() {
        bind(A.class).to(C.class);
        bind(D.class).to(DImpl.class);
    }
}

Guice.createInjector(Modules.overrides(modA, modB)); // gives me binding for A, C, E AND D with A overridden to A->C.

But what if you want to remove the binding for E in modB? I can't seem to find a way to do this without having to break the bind for E into a separate module. Is there a way?

A: 

The SPI can do this. Use Elements.getElements(modA, modB) to get a list of Element objects, representing your bindings. Iterate through that list and remove the binding whose key you'd like to remove. Then create a module from the filtered elements using Elements.getModule(). Putting it all together:

public Module subtractBinding(Module module, Key<?> toSubtract) {
  List<Element> elements = Elements.getElements(module);

  for (Iterator<Element> i = elements.iterator(); i.hasNext(); ) {
    Element element = i.next();
    boolean remove = element.acceptVisitor(new DefaultElementVisitor<Boolean>() { 
      @Override public <T> Boolean visit(Binding<T> binding) { 
        return binding.getKey().equals(toSubtract);
      }
      @Override public Boolean visitOther(Element other) {
        return false;
      }
    }); 
    if (remove) {
      i.remove();
    }
  }

  return Elements.getModule(elements);
}
Jesse Wilson
Wow that sure is a lot of magical code for something so simple. It certainly works tho. Thanks!
Y.H Wong
If you'd like something more terse, replace the visitor with "instanceof Binding" and a cast. I prefer the cast-free approach, but the net effect will be the same.
Jesse Wilson