2011-10-15 2 views
6

Contesto: Java utilizzando Guice (ultima versione)iniezione TypeLiteral con la riflessione

Ciao a tutti, è possibile iniettare qualche TypeLiteral con Guice in questo modo:

public MyClass<?,?> getMyClass(Injector injector, Class<?> a, Class<?> b) 
{ 
    //how to Inject MyClass with type a & b ? 
    //e.g : injector.getInstance(MyClass<"a class","b class">) 
} 

public interface MyClass<S,T> 
{ 
    public T do(S s); 
} 

public class ClassOne implements MyClass<String,Integer> 
{ 
    public Integer do(String s) 
    { 
      //do something 
    } 
} 

Module : 
bind.(new TypeLiteral<MyClass<String,Integer>(){}).to(ClassOne.class); 
bind.(new TypeLiteral<MyClass<String,Double>(){}).to(ClassTwo.class); 
... 

Qual è la miglior modo per gestire questo problema (con Guice)?

Grazie!

+1

duplicati di ysdx

risposta

3

Creare un ParameterizeType per il vostro tipo:

// It's supposed to be internal. 
// You could use sun.reflect.generics.reflectiveObjects but it is not portable. 
// Or you can implement it yourself (see below) 
ParameterizedType type = new com.google.inject.internal.MoreTypes.ParameterizedTypeImpl(null, MyClass.class, a, b); 

Creare un TypeLiteral da esso:

TypeLiteral typeLiteral = TypeLiteral.get(type); 

Ora creare l'istanza iniettato:

return (MyClass<A,B>) injector.getInstance(Key.get(typeLiteral)) 

In pratica si desidera implementare il ParameteriedType te:

final Type[] types = {a, b}; 
ParameterizedType type = ParameterizedType() { 
    @Override 
    public Type[] getActualTypeArguments() { 
    return types; 
    } 

    @Override 
    public Type getOwnerType() { 
    return null; 
    } 

    @Override 
    public Type getRawType() { 
    return MyClass.class; 
    }; 
} 

EDIT: In realtà, è possibile utilizzare:

Types.newParameterizedType(MyClass.class,a,b) 

vedere Guice module with type parameters

+0

Grande lavoro, funziona! Grazie ! – overflow

0

In effetti, penso che non sia possibile. I generici non sono reificati in fase di esecuzione. Ciò significa che le informazioni non sono presenti in fase di esecuzione. Quindi non importa quale tipo generico tu gli dai.

Quindi, penso che questo metodo non sia necessario. Semplicemente qualcosa di simile:

public MyClass<?,?> getMyClass(Injector injector, Class<?> a, Class<?> b) 
{ 
    return new MyClass(); 
    // Or maybe something like this, if you use custom constructors 
    // return injector.getInstance(); 
} 

Dal MyClass è un'interfaccia, ciò che si vuole raggiungere è del tutto inutile ed impossibile. Come si desidera creare un'istanza di un oggetto con un comportamento specifico quando si specifica solo il tipo param e il tipo restituito.
Penso che dovresti provare a trovare un modo diverso di lavorare.

+0

Ho aggiunto più dettagli alla mia domanda, grazie – overflow