[英]guice: automate binding of generic classes
是否可以自動化泛型類的綁定? 考慮一下:
通用接口:
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
類的綁定? 我試過使用反射無濟於事。
如果您不想明確列出實現,則必須進行某種類路徑掃描。 例如,番石榴對其ClassPath類有一些支持。
請注意,類路徑掃描與 Guice 的設計理念有些背道而馳。 為您編寫的每個實現在模塊中添加一行代碼真的有這么多額外的努力嗎?
我以某種方式設法欺騙了編譯器。
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);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.