在这个问题中,我谈论Dagger2。Dagger2 基本上由组件和模块组成。这是一个例子:
假设我有一个界面:
public interface MyCoolService {
void run();
}
和一个可能的实现:
public class MyCoolServiceImpl {
@Override
void run() {}
}
我可以使用 Dagger2 生成将实现与接口链接:
@Component(modules = {MyModule.class})
@Singleton
public interface Component {
MyCoolService getMyCoolService();
}
和
@Module
public class MyModule {
@Provides @Singleton
MyCoolService provideMyCoolService() {
return new MyCoolServiceImpl();
}
}
这是对 Dagger2 的简要介绍。现在假设我有以下界面:
public interface MySecondCoolService {
void doCoolStuff();
}
代码中没有实现MySecondCoolServiceImpl
。MySecondCoolService
相反,我有一个注释@JustForCoolStuff
来标记字段和方法。我创建了一个注释处理器,它收集所有这些注释并生成MySecondCoolServiceImpl
哪个实现MySecondCoolService
。
MySecondCoolService
我编译器在注释处理器运行之前就知道新接口。所以我可以将我的组件更改为:
@Component(modules = {MyModule.class})
@Singleton
public interface Component {
MyCoolService getMyCoolService();
MySecondCoolService getMySecondCoolService();
}
问题是我在代码中还没有实现,而且我不知道MySecondCoolService
注释处理器将生成的实现的名称。因此,我无法在MyModule
. 我能做的是更改我的注释处理器,以便它为我生成一个新模块。我的注释处理器可以生成这样的模块(MyGeneratedModule
):
@Module
public class MyGeneratedModule {
@Provides @Singleton
MySecondCoolService provide MySecondCoolService() {
return new MySecondCoolServiceImpl();
}
}
再次MyGeneratedModule
由注释处理器生成。在运行注释处理器之前我无权访问它,我也不知道它的名称。
这就是问题所在:注解处理器必须以某种方式告诉 Dagger2 有一个 Dagger2 应该考虑的新模块。由于注释处理器无法更改文件,因此无法扩展@Component(modules = {MyModule.class})
注释并将其更改为如下内容:@Component(modules = {MyModule.class, MyGeneratedModule.class})
有没有办法以MyGeneratedModule
编程方式添加到 dagger2 依赖图?如上所述,我的注释处理器如何告诉 Dagger2 在接口和实现之间应该有新的连接?
Foray: 我知道类似的事情可以在Google Guice和Google Gin中完成。一个这样做的项目是GWTP。那里有一个演示者:
public class StartPagePresenter extends ... {
@NameToken("start")
public interface MyProxy extends ProxyPlace<StartPagePresenter> {
}
...
}
它有一个接口的@NameToken
注释。ProxyPlace
在您的AbstractPresenterModule
情况下,您将视图与演示者和代理连接:
public class ApplicationModule extends AbstractPresenterModule {
bindPresenter(StartPagePresenter.class,
StartPagePresenter.MyView.class, StartPageView.class,
StartPagePresenter.MyProxy.class);
...
}
可以看到没有MyProxy
给出接口的实现。由生成器创建的实现(类似于注释处理器,但用于 GWT)。Generator 生成实现StartPagePresenter.MyProxy
并将其添加到 guide/gin 系统:
public class StartPagePresenterMyProxyImpl extends com.gwtplatform.mvp.client.proxy.ProxyPlaceImpl<StartPagePresenter> implements buddyis.mobile.client.app.start.StartPagePresenter.MyProxy, com.gwtplatform.mvp.client.DelayedBind {
private com.gwtplatform.mvp.client.ClientGinjector ginjector;
@Override
public void delayedBind(Ginjector baseGinjector) {
ginjector = (com.gwtplatform.mvp.client.ClientGinjector)baseGinjector;
bind(ginjector.getPlaceManager(),
ginjector.getEventBus());
presenter = new CodeSplitProvider<StartPagePresenter>( ginjector.getbuddyismobileclientappstartStartPagePresenter() );
...
}
}