假设我有一个界面:
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(); }
MySecondCoolService在代码中没有实现MySecondCoolServiceImpl.相反,我有一个Annotations @JustForCoolStuff来标记字段和方法.我创建了一个注释处理器,它收集所有这些注释,并生成实现MySecondCoolService的MySecondCoolServiceImpl.
编译器在注释处理器运行之前知道新的接口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,如上所述,接口和实现之间应该有一个新的布线
突袭:
我知道这样的事情可以在Google Guice和Google Gin完成.一个这样做的项目是GWTP.你有一个演示者:
public class StartPagePresenter extends ... { @NameToken("start") public interface MyProxy extends ProxyPlace<StartPagePresenter> { } ... }
它具有对ProxyPlace接口的@NameToken注释.在您的AbstractPresenterModule中,您将视图与演示者和代理人联系起来:
public class ApplicationModule extends AbstractPresenterModule { bindPresenter(StartPagePresenter.class,StartPagePresenter.MyView.class,StartPageView.class,StartPagePresenter.MyProxy.class); ... }
所以可以看到没有给出MyProxy接口的实现. Generator创建的实现(类似于注释处理器,但是用于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() ); ... } }
解决方法
Is there a way to add MyGeneratedModule programmatically to the dagger2 dependency graph?
是.在你的模块中使用一个构造函数参数.
@Module public class MyModule { private final MyCoolService serviceImpl; public MyModule(MyCoolService serviceImpl) { this.serviceImpl = serviceImpl; } @Provides @Singleton MyCoolService provideMyCoolService() { return new MyCoolServiceImpl(); } }
在构建图形时,会初始化serviceImpl:
DaggerComponent.builder().myModule(new MyModule(serviceImpl)).build();