2014-11-14 54 views
3

是否有可能自動綁定泛型類? 考慮一下:guice:自動綁定泛型類

通用接口:

public interface IAction<T> { 
    T echo(T inst); 
} 

龍子類型:

public class LongAction implements IAction<Long> {  
    @Override 
    public Long echo(Long inst) {return inst;} 
} 

字符串亞型:

public class StringAction implements IAction<String> { 
    @Override 
    public String echo(String inst) {return inst;} 
} 

自定義模塊: 公共類CustomModule擴展AbstractModule {

@Override 
protected void configure() { 
    //do this automagically? 
    bind(new TypeLiteral<IAction<String>>() {}).to(StringAction.class); 
    bind(new TypeLiteral<IAction<Long>>() {}).to(LongAction.class); 
    // 
} 

}

主要

// i know i can obtain the correct instance 
IAction<String> is = injector.getInstance(new Key<IAction<String>>(){}); 

是否可以自動綁定,以某種方式(如:基地抽象類,反射或其他)StringActionLongAction類的綁定?我試過使用反射無濟於事。

+0

你想如何自動發現'LongAction','StringAction'等?他們是在一個特定的包或什麼?如果兩個班實施'IAction ''怎麼辦? – 2014-11-15 22:43:10

+0

@TavianBarnes他們在一個特定的包。我不介意假設現在沒有兩個同樣的'T',所以不會有兩個'IAction ' – 2014-11-16 10:29:14

回答

0

我以某種方式設法欺騙編譯器。

class CustomModule extends AbstractModule { 

static class Holder<T> { 
    Class<T> param; 
    Class<IAction<T>> klass; 

    Holder(Class<?> p, Class<IAction<T>> k) { 
     param = (Class<T>) p; 
     klass = k; 
    } 
} 

// this would be similar to the result of classpath scanning 
List<IAction<?>> stuff; 

public <T> void bindSome(Class<T> typeParameter, Class<IAction<T>> implementation) { 
    Type parameterizedType = Types.newParameterizedType(IAction.class, typeParameter); 
    bind((TypeLiteral<IAction<T>>) TypeLiteral.get(parameterizedType)).to(implementation); 
} 

public CustomModule() { 
    stuff = new ArrayList<>(); 
    stuff.add(new StringAction()); 
    stuff.add(new LongAction()); 
} 

@Override 
protected void configure() { 
    for (IAction<?> act : stuff) { 
     System.out.printf("Configuring %s for %s\n", act.getTypeArguments(), act.getClass()); 
     //the following doesn't work because the compiler cannot understand that 
     //the 1st argument T is the same T in 2nd argument Class<T> 
     //bindSome(act.getTypeArguments(), act.getClass()); 

     //w00t? compiler is tricked?? <String> is erased, but the holder preserves proper class? 
     Holder<String> holder = new Holder(act.getTypeArguments(), (Class<IAction<String>>) act.getClass()); 
     bindSome(holder.param, holder.klass); 

     //this is what I want to avoid doing manually 
     //bind(new TypeLiteral<IAction<String>>() {}).to(StringAction.class); 
    } 
} 
} 
0

如果您不想明確列出實現,則必須進行某種類路徑掃描。例如,番石榴有一些支持,例如ClassPath

請注意,類路徑掃描與Guice的設計哲學有些相反。爲您編寫的每個實現添加一行到模塊真的非常費力嗎?

+0

這個問題不適用於類路徑掃描。問題與泛型類型有關。 – 2014-11-17 10:33:40

+0

啊,我沒有意識到。你已經找到了解決方案,但我已經給過它,例如在這裏:http://stackoverflow.com/a/17617369/502399 – 2014-11-17 19:52:54

+0

謝謝,我GOOGLE了它,但沒有找到你的答案。 – 2014-11-18 11:29:51