подсказка: внедрение / связывание во время выполнения в командной строке - PullRequest
3 голосов
/ 05 октября 2011

У меня следующая проблема:

   @Inject
   MyClass(Service service) {
      this.service = service;
   }

   public void doSomething() {
      service.invokeSelf(); 
   }

У меня есть один модуль

bind(service).annotatedWith(Names.named("serviceA").to(ServiceAImpl.class);
bind(service).annotatedWith(Names.named("serviceB").to(ServiceBImpl.class);

Теперь моя проблема заключается в том, что я хочу разрешить пользователю динамически выбирать инъекцию на основе времени выполнения с помощью командыпараметр строки.

public static void Main(String args[]) {
   String option = args[0];
   ..... 
}

Как я мог это сделать?Нужно ли создавать несколько модулей только для этого?

Ответы [ 3 ]

6 голосов
/ 07 октября 2011

Если вам нужно многократно выбирать во время выполнения, какая реализация использовать mapbinder очень подходит.

У вас есть такая конфигурация:

@Override
protected void configure() {
  MapBinder<String, Service> mapBinder = MapBinder.newMapBinder(binder(), String.class, Service.class);
  mapBinder.addBinding("serviceA").to(ServiceAImpl.class);
  mapBinder.addBinding("serviceB").to(ServiceBImpl.class);
}

Тогда в вашем коде просто введите карту и получите правильный сервис на основе вашего выбора:

@Inject Map<String, Service> services;

public void doSomething(String selection) {
  Service service = services.get(selection);
  // do something with the service
}

Вы можете даже заполнить инжектор выбранной службой, используя пользовательские области действия .

4 голосов
/ 05 октября 2011

Я думаю, что вы действительно хотите сделать что-то вроде этого:

public class ServiceModule extends AbstractModule {
  private final String option;

  public ServiceModule(String option) {
    this.option = option;
  }

  @Override protected void configure() {
    // or use a Map, or whatever
    Class<? extends Service> serviceType = option.equals("serviceA") ?
        ServiceAImpl.class : ServiceBImpl.class;
    bind(Service.class).to(serviceType);
  }
}

public static void main(String[] args) {
  Injector injector = Guice.createInjector(new ServiceModule(args[0]));
  // ...
}
3 голосов
/ 06 октября 2011

@ У ColinD хороший подход. Я мог бы предложить

public static void main(String[] args) {
  Module m = "serviceA".equals(args[0]) ? new AServiceModule() : new BServiceModule();
  Injector injector = Guice.createInjector(m);
  // ...
}

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

Как стиль, мне нравится сводить количество логики внутри модуля к минимуму; но опять же, просто вопрос стиля.

...