好的,所以下面的代码失败了。但是,如果存在多个潜在的 View 实例,那么在您想要使用它们的地方注入大量 Provider 提供程序会感觉很笨拙。在我的情况下这可能是可行的,但是我可以想象在其他情况下这不是很好......所以我想我会在我脑海中浮现这个问题时提出这个问题。我还没有尝试过的一种解决方案是在方法中添加虚拟的@Assisted 参数并像 factory.getView1(null) 一样调用,尽管这也不是很好。
请注意,我可以看到为什么对于 guice 实现者来说这将是一个极端情况,因为 guice 必须知道不要调用构造函数(看起来如此),而是使用提供者(它在技术上是知道的)。不过,最好询问是否有解决方案,而不是假设没有解决方案。:-)
import com.google.inject.*;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import junit.framework.Assert;
import org.junit.Test;
public class GuiceTests {
static class View1 implements Presenter.View {
String name = null;
@Override
public String getName() { return null; }
public void setName(String name) { this.name = name ;}
}
static class View2 extends View1 {}
static class Presenter {
interface View {public String getName();}
@Inject
public Presenter(@Assisted View view //, and other injected services
){}
}
interface Factory{
Presenter getPresenter(Presenter.View view);
View1 getView1();
View2 getView2();
}
static class Module extends AbstractModule
{
@Provides View1 getView1()
{
View1 view1 = new View1(); //or possibly get this from an xml generator
view1.setName("buddy");
return view1;
}
@Override
protected void configure() {
install(new FactoryModuleBuilder().implement(Presenter.class, Presenter.class)
.build(Factory.class));
}
}
/**
* We're testing the ability here for assisted injected factories
* to be used to produce entities provided by the module with NO
* assisted arguments. This way they can conveniently be used in
* conjuction with other factory assisted methods as shown below.
* This fails!
*/
@Test
public void testAssisted()
{
Injector injector = Guice.createInjector(new Module());
Factory factory = injector.getInstance(Factory.class);
View1 view1 = factory.getView1();
Assert.assertEquals("buddy", view1.getName());
Presenter presenter = factory.getPresenter(view1);
}
}
额外的上下文
Alan 在下面问“你能举一个例子说明使用这个(不调用注入器)的真实代码是什么样的吗?我不明白你为什么不把工厂和相关视图一起注入(或者定义一个带注释的为每种类型的演示者提供方法)”
所以我有一个演示者,它被可视化为有点浮动布局的卡片。该演示者具有特定的业务逻辑,可以使用一组服务对其自身进行配置。应用程序中有一个“新建”按钮,它为您提供卡片视图,引导您完成新流程(卡片上的配置)。构建卡片后,将有一个不同的视图来表示卡片......但它共享许多相同的业务逻辑......所以理想情况下,我想重用已经配置了模型的演示者......但现在附加构建的视图。使用内置视图重新创建持久卡。除非您正在关注该讨论,否则请不要阅读。
请注意,上面的代码充分地提炼了我遇到的问题。下面使事情复杂化,因为它提供了更完整的上下文。
//----------------
//on Add new entity
cardLayout.add(factory.getPresenterWithWizardView());
//-----------
//then later in the finish of the wizard
thePresenter.setView(factory.getConstructedView());
//I would prefer not to create a new presenter here, as the presenter also has layout
//state and logic that maintains and interacts with cardLayout to . Allowing for removing
//and adding a different presenter would trigger stuff affecting the state.
//--------------
//however elsewhere cards are loaded with
cardLayout.add(factory.getPresenterWithBuiltView(cardFromDb));