2010-04-05 22 views
25

Estoy tratando de migrar un pequeño proyecto, reemplazando algunas fábricas con Guice (es mi primer ensayo de Guice). Sin embargo, estoy atascado cuando trato de inyectar medicamentos genéricos. Me las arreglé para extraer un pequeño ejemplo de juguete con dos clases y un módulo:Inyectando genéricos con Guice

import com.google.inject.Inject; 

public class Console<T> { 
    private final StringOutput<T> out; 
    @Inject 
    public Console(StringOutput<T> out) { 
    this.out = out; 
    } 
    public void print(T t) { 
    System.out.println(out.converter(t)); 
    } 
} 

public class StringOutput<T> { 
    public String converter(T t) { 
    return t.toString(); 
    } 
} 

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


public class MyModule extends AbstractModule { 

    @Override 
    protected void configure() { 
    bind(StringOutput.class); 
    bind(Console.class); 
    } 

    public static void main(String[] args) { 
    Injector injector = Guice.createInjector(new MyModule()); 
    StringOutput<Integer> out = injector.getInstance(StringOutput.class); 
    System.out.println(out.converter(12)); 
    Console<Double> cons = injector.getInstance(Console.class); 
    cons.print(123.0); 
    } 

} 

Cuando ejecuto este ejemplo, todo lo que tengo es:

Excepción en hilo com.google.inject.CreationException "principal" : Errores de creación de Guice:

1) playground.StringOutput<T> cannot be used as a key; It is not fully specified. 
    at playground.MyModule.configure(MyModule.java:15) 

1 error 
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:354) 
    at com.google.inject.InjectorBuilder.initializeStatically(InjectorBuilder.java:152) 
    at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:105) 
    at com.google.inject.Guice.createInjector(Guice.java:92) 

He intentado buscar el mensaje de error, pero sin encontrar ninguna sugerencia útil. Más adelante, en las Preguntas frecuentes sobre Guice, tropiezo con una pregunta sobre cómo inyectar genéricos. He intentado añadir la continuación de la unión en el método configure:

bind(new TypeLiteral<StringOutput<Double>>() {}).toInstance(new StringOutput<Double>()); 

pero sin éxito (el mismo mensaje de error).

¿Alguien me puede explicar el mensaje de error y darme algunos consejos? Gracias.

Respuesta

27

Creo que el problema específico que está viendo es probablemente debido a la declaración bind(Console.class). También debe usar un TypeLiteral. O bien, simplemente no puedes vincular ninguno de esos enlaces y JIT se encargará de ello, ya que los dos tipos implicados aquí son clases concretas.

Además, debe recuperar el Console con:

Console<Double> cons = 
    injector.getInstance(Key.get(new TypeLiteral<Console<Double>>(){})); 

Editar: No es necesario para unirse a una instancia sólo porque usted está usando un TypeLiteral. Usted sólo puede hacer:

bind(new TypeLiteral<Console<Double>>(){}); 

Por supuesto, como he dicho anteriormente sólo podía omitir que en este caso y recuperar el Console del inyector utilizando un Key basado en la TypeLiteral y la unión sería implícito.

+0

Gracias. No estoy seguro de cómo enlazar un TypeLitteral a la Consola porque no puedo crear una instancia de Console sin una instancia de StringOutput. ¿Puedes detallar? – paradigmatic

+0

Ver mi edición ... no necesita usar toInstance(). – ColinD

+0

Acabo de intentarlo. Funciona solo si defino ambos tipos de letra Yy uso la clave para obtener la instancia. Por lo tanto, no puedo hacer que el enlace sea explícito. – paradigmatic