С Guice, как связать несколько экземпляров параметризованного класса, когда реализация использует дженерики? - PullRequest
0 голосов
/ 04 января 2012

Я пытался избежать использования своей собственной фабрики в этом случае, но я не мог найти способ сделать это с 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.

Теперь вопрос заключается в том, как я могу связать это, чтобы обеспечить разные экземпляры DefaultSerializationProvider в зависимости от разных пар E, D Чего я хочу избежать, так это создания целого ряда подклассов с единственной целью определения обобщенных элементов.

В чистой 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);

}

Заранее спасибо, Daniel

Ответы [ 2 ]

2 голосов
/ 05 января 2012

Насколько я знаю, нет способа связать 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>>() {});
0 голосов
/ 22 сентября 2018

Вы можете использовать Key.get(TypeLiteral<T> typeLiteral> для достижения параметризованной привязки к экземпляру.

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

И затем использовать как в инжекторе, основанном на конструкторе или элементе:

class MyOtherClass {

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

или

class MyOtherClass {

 @Inject
 MyClass<MyType> myClass;

}
...