2012-05-10 2 views
1

Я хотел бы знать, как представить общую версию следующие связывания, что не подведет с xxx cannot be used as a key it is not fully specifiedКак написать общий FactoryModuleBuilder?

install(new FactoryModuleBuilder(). 
    implement(new TypeLiteral<SomeClass<T,?>>(){}, 
     new TypeLiteral<SomeOtherClass<T, U>>(){}). 
    build(SomeFactory.class); 

кажется, что метод implement не доступен с параметром параметризованного типа.

+0

Мне любопытно, как выглядит ваш SomeFactory. –

+0

@johncarl Я рад поделиться, но я не знаю, как это могло бы помочь: 'interface SomeFactory > { SomeClass create (T t); } ' –

+1

Почему ваш SomeFactory параметризован?Похоже, это сработало бы: интерфейс SomeFactory { SomeClass create (T t); } –

ответ

2

Это невозможно из-за того, что Guice использует типовые литералы. TypeLiterals требуют конкретных типов и, как вы видите из исключения, не может принимать общие параметры.

процитировать @ Jesse-Вилсон

Обратите внимание, что Guice не позволяет привязок для типов, которые не полностью квалифицирован. Например, вы можете связать Map<String, Integer>, но вы не можете связать Map<K, V>. https://stackoverflow.com/a/1117878/654187

Вы можете «полностью определить» эти привязки, как описано здесь: https://stackoverflow.com/a/1120990/654187

Но я сомневаюсь, что это то, что вы хотите.

Хорошей новостью является то, вы все еще можете написать этот завод без вспомогательной инъекции легко:

public class SomeFactory{ 
    @Inject 
    private SomeDependency someDependency; 

    public <T> SomeClass<T, ?> buildSomeClass(T t){ 
     return new SomeOtherClass<T, Object>(t, someDependency); 
    } 
} 
+1

Я не уверен, как это помогает. Это не использует Guice для создания экземпляра 'SomeOtherClass'. Вся цель AssistedInject заключается в том, чтобы избежать ручного написания фабрик. –

+0

Обновлен мой ответ с дальнейшими исследованиями. –

+0

Я очень ценю все усилия, которые вы вложили в это - это просто, что предложенный вами ручной завод не будет вводить какие-либо параметры 'SomeOtherClass', а не' @ Assisted' - не так ли? –

1

Alen Vrečko posted:

Имхо лучшее, что вы можете сделать с обобщениями что-то вроде

install(new Assist2<Payment, RealPayment>(PaymentFactory.class){}); или

install(new Assist3<SomeClass<Foo, Bar>, SomeOtherClass<Foo, Bar>, SomeFactory<Foo>(){});

Должно быть довольно легко реализовать этот подход. Просто посмотрите в источнике TypeLiteral.

Если вы абсолютно необходимо параметры типа что-то вроде:

install(new CustomAssist<Baz>(){}); где

CustomAssist<T> extends Assist<SomeClass<Foo,T>,SomeOtherClass<Foo,Bar>{...

может быть возможно, но не просто реализовать. Но очень весело.

0

Чтобы следовать дальше от @johncarl

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

public class SomeFactory{ 
    @Inject 
    private Injector injector; 

    public <T> SomeClass<T, ?> buildSomeClass(T t) { 
     return new SomeOtherClass<T, Object>(t, injector.getInstance(SomeDependency)); 
    } 
} 
Смежные вопросы