使用Guice如何在实现使用泛型时绑定参数化类的多个实例?

时间:2012-01-04 16:08:42

标签: java inversion-of-control guice factories

我试图避免在这种情况下使用我自己的工厂,但是我找不到用Guice做这个的方法,也许是因为我是新手使用guice;)

我有这个接口将类型E转换为D类:

public interface SerializationProvider<E extends ValueEntity, D extends ModelDTO> {

D serialize(E entity) throws MappingSerializationException;

}

现在使用Dozer和一些反射,我可以使用一个如下所示的唯一Default类来实现它:

public class DefaultSerializationProvider<E extends ValueEntity, D extends ModelDTO>          implements
    SerializationProvider<E, D> {
private Mapper mapper;
private Class<D> dtoClass;

@Inject
public DefaultSerializationProvider(Class<D> dtoClass){
    this.dtoClass=dtoClass;
}

@Override
public D serialize(E entity) throws MappingSerializationException {
    D result=this.getNewDTOInstance();
    this.mapper.map(entity, result);
    return result;
}

protected D getNewDTOInstance() throws MappingSerializationException {
    try{
        D result=this.dtoClass.newInstance();
        return result;
    }catch(InvocationException ie){
        throw new MappingSerializationException(ie);
    }catch(IllegalAccessException iae){
        throw new MappingSerializationException(iae);
    }catch(InstantiationException iie){
        throw new MappingSerializationException(iie);
    }
}

@Inject
public void setMapper(Mapper mapper) {
    this.mapper = mapper;
}

}

请注意,我注入了Mapper。

现在问题是如何绑定它以便根据不同的对E,D提供DefaultSerializationProvider的不同实例 我想要避免的是创建一堆子类,其唯一目的是定义泛型。

在纯Java中我知道我可以提供一个工厂来提供这样的实例,如:

public interface SerializationProviderFactory {

public <E extends ValueEntity, D extends ModelDTO> SerializationProvider<E,D> get(Class<E> entityType, Class<D> dtoType);

}

一个非常简单的实现方式是:

public class DefaultSerializationProviderFactory implements
    SerializationProviderFactory {
public static final DefaultSerializationProviderFactory INSTANCE=new  DefaultSerializationProviderFactory();

@Override
public <E extends ValueEntity, D extends ModelDTO> SerializationProvider<E, D> get(
        Class<E> entityType, Class<D> dtoType) {
    return new DefaultSerializationProvider<E, D>(dtoType);
}

}

现在问题是如何使用Guice实现这种工厂? 或者有更好的方法吗?

工厂的一个简单用例是:

public MessureUnitDTO serializeUnit(MessureUnit unit){
    SerializationProviderFactory factory=DefaultSerializationProviderFactory.INSTANCE;
    SerializationProvider<MessureUnit, MessureUnitDTO> provider=factory.get(MessureUnit.class, MessureUnitDTO.class);
    return provider.serialize(unit);

}

提前致谢, 丹尼尔

2 个答案:

答案 0 :(得分:2)

据我所知,没有办法将DefaultSerializationProvider绑定到所有可能的类型参数。但是如果你可以枚举你需要转换的所有类型参数,你可以使用这样的绑定:

bind(new TypeLiteral<SerializationProvider<MessureUnit, MessureUnitDTO>>() {})
    .toInstance(new DefaultSerializationProvider<MessureUnit, MessureUnitDTO>(MessureUnitDTO.class));

如果您愿意,可以通过在toInstance中注入类型文字来避免使用DefaultSerializationProvider

@Inject public DefaultSerializationProvider(TypeLiteral<D> dtoType) {
  this.dtoClass = (Class<D>) dtoType.getRawType();
}

然后你可以使用这样的绑定:

bind(new TypeLiteral<SerializationProvider<MessureUnit, MessureUnitDTO>>() {})
    .to(new TypeLiteral<DefaultSerializationProvider<MessureUnit, MessureUnitDTO>>() {});

答案 1 :(得分:0)

您可以使用Key.get(TypeLiteral<T> typeLiteral>来实现对实例的参数化绑定。

MyClass<MyType> myClassInstanceOfMyType = new MyClass<MyType>();    
bind(Key.get(new TypeLiteral<MyClass<MyType>>(){})).toInstance(myClassInstanceOfMyType);

然后在构造函数或基于成员的注入中使用as:

class MyOtherClass {

  @Inject
  MyOtherClass(MyClass<MyType> myClass){}
  //stuff
}

class MyOtherClass {

 @Inject
 MyClass<MyType> myClass;

}