2010-05-18 1 views
4

Так, по моему тестирования, если у вас есть что-то вроде:Как вычесть привязку с помощью переопределения модуля Guice?

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. 

Но что, если вы хотите, чтобы удалить привязку для Е в MODB? Я не могу найти способ сделать это, не нарушая привязку для E в отдельный модуль. Есть ли способ?

+0

Просто глупая идея, может быть, но вы пытаетесь связать (E.class) .то (E.class)? (Можно ли связать интерфейс с другим интерфейсом?) –

+0

Да, вы можете привязать 1 привязку к другому связыванию неограниченно, если конечная точка привязки указывает на конкретный класс или поставщика. Что касается bind (E.class) .to (E.class), я подал ошибку об этом 3 года назад, и это выходит в 2.1. http://code.google.com/p/google-guice/issues/detail?id=171 –

ответ

9

SPI может это сделать. Используйте Elements.getElements(modA, modB), чтобы получить список Element объектов, представляющих ваши привязки. Перейдите через этот список и удалите привязку, ключ которой вы хотите удалить. Затем создайте модуль из фильтрованных элементов, используя Elements.getModule(). Соединив все это:

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); 
} 
+0

Ничего себе, это очень много волшебного кода для чего-то такого простого. Это, безусловно, работает. Благодаря! –

+1

Если вы хотите что-то более краткое, замените посетителя «instanceof Binding» и литой. Я предпочитаю подход без литья, но чистый эффект будет таким же. –

2

Guice 4.0beta вернётся только для чтения Список элементов. Поэтому я изменяю код Джесси Уилсона следующим образом. Вам нужно предоставить список модулей и вычесть привязку к цели, которую вы хотите заменить.

Injector injector = Guice.createInjector(new TestGuiceInjectionModule(), Utils.subtractBinding(new GuiceInjectionModule(),Key.get(IInfoQuery.class))); 

Функция

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

    return Elements.getModule(Collections2.filter(elements, input -> { 
     if(input instanceof Binding) 
     { 
      return !((Binding) input).getKey().equals(toSubtract); 
     } 

     return true; 
    })); 
} 
Смежные вопросы