Как внедрить список с различными реализациями одного и того же интерфейса в сценарии с вложенным модулем через Guice? - PullRequest
0 голосов
/ 24 октября 2018

Существует интерфейс DCE, который реализуется классом DCEImpl, который имеет зависимость, скажем, от строки S, которую он получает через конструктор.

Юниверс S ограничен, скажем, S может толькопринимать значения {'A', 'B', 'C'}.

Существует уже существующий модуль Guice, который принимает значение S в своем конструкторе, а затем связывает интерфейс DCE с правильно инициализированной версией 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));
    }
}

Теперь у меня естькласс C, который нуждается в List<DCE> со всеми 3 реализациями (на самом деле намного больше, чем 3, для примера используется 3).

Я хочу добавить этот список через Guice в C.Для этого я создал новый модуль DCEPModule, который будет обеспечивать List<DCE> следующим образом:

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

Моя проблема в том, что я не хочу вызывать новый инжектор в этом модулепотому что DCEPModule будет установлен другим модулем.

public class NewModule extends AbstractModule {
   protected void configure() {
      install(DCEPModule);
    }

} ​​

Я хочу получить List<DCE> без явного создания нового инжектора в DCEPModule.

1 Ответ

0 голосов
/ 24 ноября 2018

Вы можете достичь этого, используя Multibinder ( javadoc , wiki ).Вот пример:

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

Теперь мультибиндер предоставит Set<Snack>.Если вам абсолютно необходим List вместо Set, то вы можете добавить метод к своему модулю, например так:

@Provides
public List<Snack> getSnackList(Set<Snack> snackSet) {
    return new ArrayList(snackSet);
}

Вы можете добавить реализации к одному и тому же Multibinding в более чем одном модуле.Когда вы звоните Multibinder.newSetBinder(binder, type), это не обязательно создает новый Multibinding.Если для этого типа уже существует мультисвязь, вы получите существующую мультисвязь.

...