使用注释处理延迟绑定到Dagger2图形

11 java dependency-injection guice dagger dagger-2

在这个问题中我谈到了Dagger2.Dagger2基本上由组件和模块组成.这是一个例子:

假设我有一个界面:

public interface MyCoolService {
  void run();
}
Run Code Online (Sandbox Code Playgroud)

以及可能的实施:

public class MyCoolServiceImpl {
   @Override
   void run() {}
}
Run Code Online (Sandbox Code Playgroud)

我可以使用Dagger2生成链接实现与接口:

@Component(modules = {MyModule.class})
@Singleton
public interface Component {    
    MyCoolService getMyCoolService();       
}
Run Code Online (Sandbox Code Playgroud)

@Module
public class MyModule {

    @Provides @Singleton
    MyCoolService provideMyCoolService() {
        return new MyCoolServiceImpl();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是Dagger2的简要介绍.现在假设我有以下界面:

public interface MySecondCoolService {
  void doCoolStuff();
}
Run Code Online (Sandbox Code Playgroud)

没有执行MySecondCoolServiceImplMySecondCoolService代码.相反,我有一个标注@JustForCoolStuff字段和方法的注释.我创建了一个Annotation处理器,它收集所有这些Annotations并生成MySecondCoolServiceImpl哪些实现MySecondCoolService.

我是编译器MySecondCoolService在注释处理器运行之前知道新接口的.所以我可以将我的组件更改为:

@Component(modules = {MyModule.class})
@Singleton
public interface Component {    
    MyCoolService getMyCoolService();   
    MySecondCoolService getMySecondCoolService();    
}    
Run Code Online (Sandbox Code Playgroud)

问题是,我没有一个尚未实现的代码,我不知道的实现的名称MySecondCoolService将由一个注释处理器生成.因此,我无法在接口中连接正确的实现MyModule.我可以做的是更改我的注释处理器,以便它为我生成一个新模块.我的注释处理器可以MyGeneratedModule像这样生成一个module():

@Module
public class MyGeneratedModule {

    @Provides @Singleton
    MySecondCoolService provide MySecondCoolService() {
        return new MySecondCoolServiceImpl();
    }
}  
Run Code Online (Sandbox Code Playgroud)

再次MyGeneratedModule由注释处理器生成.我在运行注释处理器之前无法访问它也不知道名称.

问题在于:注释处理器不得不告诉Dagger2 Dagger2应该考虑一个新的模块.由于注释处理器无法更改文件,因此无法扩展@Component(modules = {MyModule.class})注释并将其更改为如下所示:@Component(modules = {MyModule.class, MyGeneratedModule.class})

有没有办法以MyGeneratedModule编程方式添加到dagger2依赖图?我的注释处理器如何告诉Dagger2接口和实现之间应该有新的连接,如上所述?


Foray: 我知道可以在Google GuiceGoogle Gin中完成类似的事情.这样做的项目是GWTP.你有一个演示者:

public class StartPagePresenter extends ... {
    @NameToken("start")
    public interface MyProxy extends ProxyPlace<StartPagePresenter> {
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

它有@NameToken一个ProxyPlace接口的注释.在您AbstractPresenterModule使用演示者和代理连接视图时:

public class ApplicationModule extends AbstractPresenterModule {

        bindPresenter(StartPagePresenter.class,
                StartPagePresenter.MyView.class, StartPageView.class,
                StartPagePresenter.MyProxy.class);
       ...
}
Run Code Online (Sandbox Code Playgroud)

因此可以看出没有MyProxy给出接口的实现.由Generator生成的实现(类似于注释处理器,但用于GWT).Generator生成实现StartPagePresenter.MyProxy并将其添加到指南/杜松子酒系统:

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() );
    ...
    }
  }
Run Code Online (Sandbox Code Playgroud)

ben*_*nyl 0

好吧,看来你必须对此进行反思......

@Module
public class MyGeneratedModule {

    @Provides @Singleton
    MySecondCoolService provide MySecondCoolService() {
        try {
            return (MySecondCoolService) Class.forName("package.MySecondCoolServiceImpl").newInstance(); 
        } catch (Exception ex) { ... }
    }
}  
Run Code Online (Sandbox Code Playgroud)