是否可以自动化泛型类的绑定? 考虑一下:
通用界面:
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>>(){});
是否有可能以某种方式(例如:基本抽象类,反射或其他)自动绑定StringAction
和LongAction
类的绑定?我尝试使用反射无济于事。
答案 0 :(得分:0)
如果您不想明确列出实现,则必须进行某种类路径扫描。例如,Guava对其ClassPath类有一些支持。
请注意,类路径扫描与Guice的设计理念有些相反。对于您编写的每个实现,为模块添加一行是否真的需要额外的努力?
答案 1 :(得分: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);
}
}
}