1

I want to inject an object of a generic interface type into another object

class InjectionTarget {
    @Inject IGenericType<String, Integer> object; 
}

interface IGenericType<A, B> {
    void foo(A a);
    void bar(B b);
}

class GenericTypeImpl<A, B> implements IGenericType<A, B> {
    List<A> someListA = new ArrayList();
    List<B> someListB = new ArrayList();

    @Override
    public void foo(A a) {
        someListA.add(a);
    }

    @Override
    public void bar(B b) {
        someListB.add(b);
    }
}
    
// dagger component and actual injection skipped for clarity

I tried to use a provider method, but it causes compilation error (@Provides methods may not have type parameters)

@Module
class Module {
  
  // this doesn't compile
  @Provides
  <A, B> IGenericType<A, B> getGenericType() {
    return new GenericTypeImpl<A, B>();
  }
}

So I had to move type parameters from @Provides method to class. Then, since:

  • Modules with type parameters must be abstract
  • abstract module cannot have instance @Provides methods (all must be static)
  • non-static type variable A and B cannot be referenced from a static context

I cannot use @Provides method anymore (even static one, because of type variables), so I ended up with @Binds using @Inject constructor for implementation

@Module
public abstract class TestModule<A, B> {

    @Binds
    abstract IGenericType<A, B> getGenericType(GenericTypeImpl<A, B> object);
}

class GenericTypeImpl<A, B> implements IGenericType<A, B> {
    ...       
    @Inject
    public GenericTypeImpl() {}
    ...
}

but this fails too with

IGenericType<java.lang.String,java.lang.Integer> cannot be provided without an @Provides-annotated method

So it seems a hopeless case. Is there any way to workaround this ? I prefer to avoid adding provider methods for every single type combination I'll use (I expect there will be many of these) and stay with one generic provider/binds method.

Piotr Śmietana
  • 393
  • 2
  • 19

0 Answers0