2014-11-14 75 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