Inject Generic Implementation using Guice

Sean Carpenter picture Sean Carpenter · Nov 21, 2010 · Viewed 31.9k times · Source

I would like to be able to inject a generic implementation of a generic interface using Guice.

public interface Repository<T> {
  void save(T item);
  T get(int id);
}

public MyRepository<T> implements Repository<T> {
  @Override
  public void save(T item) {
    // do saving
    return item;
  }
  @Override
  public T get(int id) {
    // get item and return
  }
}

In C# using Castle.Windsor, I'd be able to do:

Component.For(typeof(Repository<>)).ImplementedBy(typeof(MyRepository<>))

but I don't think the equivalent exists in Guice. I know I can use TypeLiteral in Guice to register individual implementations, but is there any way to register them all at once like in Windsor?

Edit:

Here's an example of usage:

Injector injector = Guice.createInjector(new MyModule());
Repository<Class1> repo1 = injector.getInstance(new Key<Repository<Class1>>() {});
Repository<Class2> repo2 = injector.getInstance(new Key<Repository<Class2>>() {});

Although the more likely usage would be injection into another class:

public class ClassThatUsesRepository {
  private Repository<Class1> repository;

  @Inject
  public ClassThatUsesRepository(Repository<Class1> repository) {
    this.repository = repository;
  }
}

Answer

Kdeveloper picture Kdeveloper · Nov 21, 2010

In order to use generics with Guice you need to use the TypeLiteral class to bind the generic variants. This is an example of how you're Guice injector configuration could look like:

package your-application.com;

import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;

public class MyModule extends AbstractModule {
  @Override
  protected void configure() {
    bind(new TypeLiteral<Repository<Class1>>(){})
      .to(new TypeLiteral<MyRepository<Class1>>(){});
  }
}

(Repository is the generic interface, MyRepository is the generic implementation, Class1 is the specific class used in the generics).