Обобщите пример ног робота guice с помощью Multibinding

У меня есть этот вариант использования, который очень похож на пример ног робота в Guice, за исключением того, что я не знаю, сколько у меня «ног». Поэтому я не могу использовать аннотации, необходимые для примера с роботизированными ногами.

Я ожидаю собрать все эти «ноги» в java.util.Set с расширением Guice Multibindings.

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

Для справки и примера кода см. Пример ног робота здесь: http://code.google.com/p/google-guice/wiki/FrequentAskedQuestions #How_do_I_build_two_similar_but_slightly_different_trees_of_objec


Вот мой точный вариант использования:

У меня есть следующее:

// Main application
public interface MyTree {...}
public interface MyInterface {
  public MyTree getMyTree() {}
}
public abstract class MyModule extends PrivateModule {}
public class MyManager {
  @Inject MyManager (Set interfaces){ this.interfaces = interfaces }
}
public class MainModule extends AbstractModule {
  public void configure () {
    // Install all MyModules using java.util.ServiceLoader.
  }
}


// In expansion "square.jar"
public class SquareTree implements MyTree {...}
public class SquareImplementation implements MyInterface {
  @Inject SquareImplementation (MyTree tree) { this.tree = tree; }
  public MyTree getMyTree () { return this.tree; }
}
public class SquareModule extends MyModule { // correctly defined as a ServiceLoader's service.
  public void configure () {
    // How to make this public IN a multibinder's set?
    bind(MyInterface.class).to(SquareImplementation.class);

    // Implementation specific to the Squareimplementation.
    bind(MyTree.class).to(SquareTree.class);
  }
}

// In expansion "circle.jar"
public class CircleTree implements MyTree {...}
public class CircleImplementation implements MyInterface {
  @Inject CircleImplementation (MyTree tree) { this.tree = tree; }
  public MyTree getMyTree () { return this.tree; }
}
public class CircleModule extends MyModule { // correctly defined as a ServiceLoader's service.
  public void configure () {
    // How to make this public IN a multibinder's set?
    bind(MyInterface.class).to(CircleImplementation.class);

    // Implementation specific to the Circle implementation.
    bind(MyTree.class).to(CircleTree.class);
  }
}

Поскольку я говорю о банках расширения, я сначала не знаю их, я даже не знаю, сколько из них они существуют: мне нужно загрузить в MyModule s с помощью juServiceLoader , и каждый модуль должен определять реализацию MyInterface (эти две части подходят).

Задача состоит в том, чтобы получить все реализации MyInterface в одном наборе (в MyManager ). Как я могу это сделать?


Решение, полностью основанное на ответе Джесси:

// Create the set binder.
Multibinder interfaceBinder = Multibinder.newSetBinder(binder(), MyInterface.class, MyBinding.class);

// Load each module that is defined as a service.
for (final MyModule module : ServiceLoader.load(MyModule.class)) {

  // Generate a key with a unique random name, so it doesn't interfere with other bindings.
  final Key myKey = Key.get(MyInterface.class, Names.named(UUID.randomUUID().toString()));
  install(new PrivateModule() {
    @Override protected void configure() {
      // Install the module as part of a PrivateModule so they have full hands on their own implementation.
      install(module);
      // Bind the unique named key to the binding of MyInterface.
      bind(myKey).to(MyInterface.class);
      // Expose the unique named binding
      expose(myKey);
    }
  });
  // bind the unique named binding to the set
  interfaceBinder.addBinding().to(myKey);
}

Это позволяет мне не заставлять «клиента» расширять PrivateModule, а использовать любую реализацию модуля, если MyModule является интерфейсом, расширяющим модуль.

6
задан Jeff Axelrod 27 January 2012 в 15:02
поделиться