Внедрение универсальной фабрики в Гисе

Следующий код является примером фабрики, которая производитBar<T> учитываяFoo<T>, Фабрике все равно, чтоT есть: для любого типаT, это может сделатьBar<T> изFoo<T>.

import com.google.inject.*;
import com.google.inject.assistedinject.*;

class Foo<T> {
  public void flip(T x) { System.out.println("flip: " + x); }
}

interface Bar<T> {
  void flipflop(T x);
}

class BarImpl<T> implements Bar<T> {
  Foo<T> foo;

  @Inject
  BarImpl(Foo<T> foo) { this.foo = foo; }

  public void flipflop(T x) { foo.flip(x); System.out.println("flop: " + x); }
}

interface BarFactory {
  <T> Bar<T> create(Foo<T> f);
}

class Module extends AbstractModule {
  public void configure() {
    bind(BarFactory.class)
      .toProvider( 
          FactoryProvider.newFactory( BarFactory.class, BarImpl.class ) 
                   );
  }
}

public class GenericInject {
  public static void main(String[] args) {
    Injector injector = Guice.createInjector(new Module());

    Foo<Integer> foo = new Foo<Integer>();
    Bar<Integer> bar = injector.getInstance(BarFactory.class).create(foo);
    bar.flipflop(0);
  }
}

Когда я запускаю код, я получаю следующие ошибки от Guice:

1) No implementation for BarFactory was bound.
  at Module.configure(GenericInject.java:38)

2) Bar<T> cannot be used as a key; It is not fully specified.

Единственная ссылка, которую я могу найти на дженерики в документации Guice, говорит об использованииTypeLiteral, Но у меня нет буквального типа, у меня есть общий заполнитель, который вообще не имеет отношения к фабрике. Какие-нибудь советы?

Ответы на вопрос(2)

class BarImplFactory implements BarFactory {
  public <T> Bar<T> create(Foo<T> f) {
    return new BarImpl(f);
  }
}

Привязка становится

bind(BarFactory.class).to(BarImplFactory.class);
 Chris Conway12 мая 2012 г., 14:25
Нет, я так не думаю. Вам все еще нужно будет предоставить свои собственные Foos.
 Shuo26 февр. 2013 г., 08:01
@Jeff Axelrod, Вы можете добавить другие параметры конструктора BarImpl, сначала вставив конструктор BarImplFactory, а затем скопировав эти значения.
 Jeff Axelrod10 мая 2012 г., 23:39
Будет ли Guice вводитьBarImplдругие параметры конструктора, даже если его конструктор вызывается явно без Guice?

похожей на пружинную, то на самом деле нет смысла связывать общий экземпляр. Вы связываете конкретные экземпляры с ключами, поэтому, когда другой экземплярный класс помечает что-то с помощью @Inject BarFactory, вы получаете определенный созданный экземпляр.

Поскольку ваша реализация является общей, вы не предоставили достаточно информации для внедрения конкретного экземпляра. Хотя я не использовал factoryprovider, я предполагаю, что вам нужно привязать Barfactory к полностью параметризованному экземпляру, например,BarImpl<Concrete> вместо BarImpl)

Между прочим, поскольку вы связываете BarFactory.class, если вы хотите связать несколько экземпляров, вам придется как-то их отклонять, либо по имени, что-то вроде (не проверял синтаксис, но)

bind(BarFactory.class).annotatedWith(Names.named("name1"))
      .toProvider( 

or by generics, bind(BarFactory<Concrete>).toProvider...
 Chris Conway25 сент. 2010 г., 15:15
BarFactory не является универсальным, поэтому имеет смысл подключить его так, как я его написал. Параметризованный экземпляр Bar не будет соответствовать контракту: create необходимо взять Foo <T> и вернуть Bar <T> для любого T.

Ваш ответ на вопрос