Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guice module with type parameters

I spent some time wondering if it is possible to write a guice module which itself is parametrized with type T and uses its type parameter to specify bindings.

Like in this (not working) example:

interface A<T> {} 
class AImpl<T> implements A<T>{} 
interface B<T> {} 
class BImpl<T> implements B<T> {} 

class MyModule<T> extends AbstractModule { 
    @Override 
    protected void configure() { 
        bind(new TypeLiteral<A<T>>(){}).to(new TypeLiteral<AImpl<T>>(){});
        bind(new TypeLiteral<B<T>>(){}).to(new TypeLiteral<BImpl<T>>(){}); 
    } 
} 

I tried different approaches passing trying to pass T to MyModule as instance of Class/TypeLiteral but none of them worked. Help appreciated.

Regards, Łukasz Osipiuk

like image 344
losipiuk Avatar asked Sep 12 '11 09:09

losipiuk


People also ask

What is @named annotation in Guice?

Guice comes with a built-in binding annotation @Named that takes a string: public class RealBillingService implements BillingService { @Inject public RealBillingService(@Named("Checkout") CreditCardProcessor processor, TransactionLog transactionLog) { ... }

What is @inject annotation in Guice?

Annotation Type Inject. @Target(value={METHOD,CONSTRUCTOR,FIELD}) @Retention(value=RUNTIME) @Documented public @interface Inject. Annotates members of your implementation class (constructors, methods and fields) into which the Injector should inject values.

What does @inject do Guice?

Note that the only Guice-specific code in the above is the @Inject annotation. This annotation marks an injection point. Guice will attempt to reconcile the dependencies implied by the annotated constructor, method, or field.

What is abstract module in Guice?

* AbstractModule is a helper class used to add bindings to the Guice injector. * * <p>Simply extend this class, then you can add bindings by either defining @Provides methods (see.


1 Answers

For that you will have to build each TypeLiteral from scratch, using com.google.inject.util.Types. You could do something like that:

class MyModule<T> extends AbstractModule {
    public MyModule(TypeLiteral<T> type) {
        _type = type;
    }

    @Override protected void configure() {
        TypeLiteral<A<T>> a = newGenericType(A.class);
        TypeLiteral<AImpl<T>> aimpl = newGenericType(AImpl.class);
        bind(a).to(aimpl);
        TypeLiteral<B<T>> b = newGenericType(B.class);
        TypeLiteral<BImpl<T>> bimpl = newGenericType(BImpl.class);
        bind(b).to(bimpl);
    }

    @SuppressWarnings("unchecked")
    private <V> TypeLiteral<V> newGenericType(Class<?> base) {
        Type newType = Types.newParameterizedType(base, _type.getType());
        return (TypeLiteral<V>) TypeLiteral.get(newType);
    }

    final private TypeLiteral<T> _type;
}

Please note that the private method newGenericType() will perform no control on types, it is your responsibility, in configure(), to make sure that generic types can be correctly built with that method.

like image 146
jfpoilpret Avatar answered Sep 29 '22 08:09

jfpoilpret