11

この質問では、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();
}

コード内の実装はありませんMySecondCoolServiceImplMySecondCoolService代わりに、@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 GuiceGoogle 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インターフェイスの実装は指定されていません。Generator によって作成された実装 (アノテーション プロセッサに似ていますが、GWT 用)。そこでジェネレーターはの実装を生成し、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() );
    ...
    }
  }

4

2 に答える 2

0

うーん、これは反射に頼る必要があるようです...

@Module
public class MyGeneratedModule {

    @Provides @Singleton
    MySecondCoolService provide MySecondCoolService() {
        try {
            return (MySecondCoolService) Class.forName("package.MySecondCoolServiceImpl").newInstance(); 
        } catch (Exception ex) { ... }
    }
}  
于 2015-06-06T10:27:21.497 に答える