Используйте GIN для внедрения фабрики Generics в ListEditor.

Я написал фабрику, способную создавать ListEditor любого типа:

public interface ListEditorFactory<T, E extends Editor<T>> {
    ListEditor<T, E> create(InsertPanel panel);
}

И его реализация:

public class ListEditorFactoryImpl<T, E extends Editor<T> & IsWidget> implements ListEditorFactory<T, E> {
    private final Provider<E> editorProvider;

    @Inject
    public ListEditorFactoryImpl(Provider<E> editorProvider) {
        this.editorProvider = editorProvider;
    }

    @Override
    public ListEditor<T, E> create(final InsertPanel panel) {
        return ListEditor.of(new EditorSource<E>() {
            @Override
            public E create(int index) {
                final E e = editorProvider.get();
                panel.add(e.asWidget());
                return e;
            }

            @Override
            public void dispose(E e) {
                e.asWidget().removeFromParent();
            }

            @Override
            public void setIndex(E editor, int index) {
                panel.insert(editor.asWidget(), index);
            }
        });
    }
}

Это работает очень хорошо, если я непосредственно создаю экземпляр factory с помощью Provider, введенного Gin:

ListEditor<NoteDTO, CharacterNoteScreen> notesEditor;
@Inject @UiField(provided = true) FlowPanel notePanel;

@Inject
protected void init(Provider<CharacterNoteScreen> characterNoteProvider) {
    final ListEditorFactory<NoteDTO, CharacterNoteScreen> listEditorFactory = new ListEditorFactoryImpl<NoteDTO, CharacterNoteScreen>(characterNoteProvider);
    notesEditor = listEditorFactory.create(notePanel);

Но если я хочу ввести весь ListEditorFactory следующим образом:

@Inject
protected void init(ListEditorFactory<NoteDTO, CharacterNoteScreen> listEditorFactory) {
    notesEditor = listEditorFactory.create(notePanel);

Джин жалуется на простую привязку bind(ListEditorFactory.class).to(ListEditorFactoryImpl.class);:

[ERROR] Generator 'com.google.gwt.inject.rebind.GinjectorGenerator' threw an exception while rebinding 'net.test.client.MyGinjector'
com.google.inject.ConfigurationException: Guice configuration errors:
1) javax.inject.Provider<E> cannot be used as a key; It is not fully specified.

Я пробовал с bind(new TypeLiteral<ListEditorFactory<?, ?>>() {}).to(new TypeLiteral<ListEditorFactoryImpl<?, ?>>() {});, но получил

java.lang.IllegalArgumentException: Expected a Class, ParameterizedType, or GenericArrayType, but <?> is of type com.google.inject.internal.MoreTypes$WildcardTypeImpl

Привязка bind(new TypeLiteral<ListEditorFactory<NoteDTO, CharacterNoteScreen>>() {}).to(new TypeLiteral<ListEditorFactoryImpl<NoteDTO, CharacterNoteScreen>>() {}); работает, но родовая фабрика теряет большую часть своего интереса.

Знаете ли вы общий способ объявить эту привязку?

Спасибо


person Arnor    schedule 19.07.2013    source источник


Ответы (1)


Мне удалось найти решение, избавившись от интерфейса ListEditorFactory, больше не нужно объявлять привязку в модуле gin.

Я могу напрямую внедрить реализацию без каких-либо проблем:

@Inject
protected void init(ListEditorFactoryImpl<NoteDTO, CharacterNoteScreen> listEditorFactory) {
    notesEditor = listEditorFactory.create(notePanel);

Если gin может внедрить это, я не вижу причин, по которым он не может внедрить его через интерфейс, кроме неправильного объявления привязки.

Поэтому, даже если я доволен своим решением, я оставлю вопрос открытым, потому что это может быть способ объявить привязку.

person Arnor    schedule 25.07.2013
comment
Согласно Inject a Class‹T› с GIN, Gin не может вводить дженерики с подстановочными знаками type, потому что он выполняет всю свою работу во время компиляции, когда эффективный тип неизвестен. Я до сих пор не понимаю, как это работает без объявления привязки, я думаю, что есть та же проблема. В любом случае я принимаю этот ответ, потому что кажется, что лучшего решения нет. - person Arnor; 28.08.2013