У меня есть код, который выглядит следующим образом:
class A {
X x;
A() {
Class<? extends X> cls = ...;
Module module = ...;
Injector injector = Guice.createInjector(module);
x = injector.getInstance(cls);
}
}
Конкретный тип cls
определяется только во время выполнения и не известен до вызова этого конструктора.
Моя проблема сейчасожидается, что конструкторы cls
будут выдавать проверенные исключения, и я хотел бы обработать их (если это возможно, не разворачивая их из ProvisionException).Документация Guice говорит, что я должен использовать расширение бросающих провайдеров, которое кажется здесь сложным.Есть ли более простой способ, чем этот:
interface MyCheckedProvider<T> extends CheckedProvider<T> {
T get() throws MyCheckedException;
}
class XImplProvider implements MyCheckedProvider<X> {
@Inject dependency1;
@Inject dependency1;
X get() throws MyCheckedException {
return new XImpl(dependency1, dependency2);
}
}
class ProviderHolder {
@Inject MyCheckedProvider<X> provider;
}
class A {
X x;
A() {
Class<? extends MyCheckedProvider<X>> providerClass = ...;
Module module = new AbstractModule() {
void configure() {
...
ThrowingProviderBinder.create(binder())
.bind(MyCheckedProvider.class, X.class)
.to(providerClass.class);
}
};
Injector injector = Guice.createInjector(module);
ProviderHolder holder = injector.getInstance(ProviderHolder.class);
try {
x = holder.provider.get();
catch (MyCheckedException e) {
...
}
}
}
Интерфейс MyCheckedProvider
будет в порядке, потому что он будет многократно использоваться в нескольких местах, но мне понадобится отдельный класс ProviderHolder
в каждом месте, гдетребуется нечто подобное, и мне нужна конкретная реализация провайдера для каждого класса, реализующего X (которых может быть много).Так что это даже больше, чем просто внедрение XFactory и написание XFactoryImpl для каждого конкретного типа (чего я пытался избежать).
Я надеялся, что смогу сделать что-то вроде
injector.getInstance(new TypeLiteral<MyCheckedProvider<X>>() {});
или
injector.getCheckedProvider(cls, MyCheckedException.class);
, но, похоже, это не поддерживается.