2010-05-18 8 views
4

Donc, d'après mes tests, si vous avez quelque chose comme:Comment soustraire une liaison en utilisant un remplacement de module 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. 

Mais si vous voulez supprimer la liaison E dans Modb? Je n'arrive pas à trouver un moyen de le faire sans avoir à casser la liaison pour E dans un module séparé. Y a-t-il un moyen?

+0

Juste une idée stupide, peut-être, mais avez-vous essayé bind (E.class) .pour (E.class)? (Pouvez-vous même lier une interface à une autre interface?) –

+0

Oui, vous pouvez lier indéfiniment une liaison à une autre liaison, tant que le point final d'une liaison pointe vers une classe ou un fournisseur concret. Comme pour lier (E.class) .to (E.class), j'ai déposé un bug à ce sujet il y a 3 ans et il sortira en 2.1. http://code.google.com/p/google-guice/issues/detail?id=171 –

Répondre

9

Le SPI peut le faire. Utilisez Elements.getElements(modA, modB) pour obtenir la liste des objets Element, représentant vos liaisons. Itérez dans cette liste et supprimez la liaison dont vous souhaitez supprimer la clé. Créez ensuite un module à partir des éléments filtrés à l'aide de Elements.getModule(). Tout mettre ensemble:

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

Wow c'est sûr qu'il y a beaucoup de code magique pour quelque chose d'aussi simple. Cela fonctionne certainement. Merci! –

+1

Si vous souhaitez quelque chose de plus concis, remplacez le visiteur par "instanceof Binding" et un cast. Je préfère l'approche sans plâtre, mais l'effet net sera le même. –

2

Guice 4.0beta retournera en lecture seule la liste des éléments. Donc, je modifie le code de Jesse Wilson comme suit. Ce que vous devez faire est de fournir la liste des modules et soustraire la liaison cible, que vous voulez remplacer.

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

Fonction

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