7

エントリ ポイントで依存関係を挿入するために GIN を使用する webapp があります。

private InjectorService injector = GWT.create(InjectorService.class);

@GinModules({PlaceContollerInject.class, RootViewInject.class})
public interface InjectorService extends Ginjector {

  RootView getRootView();
  PlaceController getPlaceConroller();

}

public class RootViewInject extends AbstractGinModule {

  @Override
  protected void configure() {
    bind(RootView.class).to(RootViewImpl.class);
  }
}

別の RootView 実装を使用するモバイル バージョンが必要です。依存関係は、次のモジュールで説明されています

public class RootViewMobileInject extends AbstractGinModule {

  @Override
  protected void configure() {
    bind(RootView.class).to(RootViewMobileImpl.class);
  }
}

問題は、モバイル バージョンまたはデフォルト バージョンのどちらが必要かを条件付きで依存関係を選択する方法です。GWT-GIN Multiple Implementationsを見たことがありますが、プロバイダーが依存関係のチェーンを壊し、Factory パターンがテスト可能性を壊すため、その解決策を見つけていません。こちらの「Guice を使用した Big Modular Java」ビデオ(12 分) では、モジュールを使用した Guice のインジェクターが Factory の代替として紹介されました。したがって、私の質問は、アプリのモバイル バージョンとデフォルト バージョン (MobileFactory や DefaultFactory など) 用に異なる Ginjector を作成する必要があるか、それとも悪い習慣であり、必要なすべてのバージョンで Ginjector の 1 つのインスタンスを構成する必要があるかということです。たとえば、このような注釈バインディングを使用します。

public class RootViewMobileInject extends AbstractGinModule {

  @Override
  protected void configure() {
    bind(RootView.class).annotatedWith(Mobile.class).to(RootViewMobileImpl.class);
  }
}

GWT エントリ ポイントで @Mobile アノテーション付きバインディングを使用する

  @Inject
  private void setMobileRootView(@Mobile RootView rw) {
    this.rw = rw;
  }

上記のような単純化された例では、可能かもしれません。ただし、アプリケーションに、モバイル バージョンとデフォルト バージョンを必要とする依存関係がさらにある場合。テスト不可能な「醜い」(Guiceのプレゼンテーションで言われたように)工場に戻ったようです。私の英語でごめんなさい。どんな助けでも大歓迎です。

4

2 に答える 2

9

クラス置換を使用して、ユーザーエージェントに応じて InjectorService の異なるバージョンをバインドする、GWT 遅延バインディングを使用することをお勧めします。これにより、モバイル版にはコンパイル済み (およびダウンロード済み) のモバイル実装のみが含まれるようになります。

したがって、InjectorServiceDesktop、InjectorServiceMobile の両方が InjectorService から拡張され、次に GWT.create(InjectorService.class) があり、遅延バインディングに使用する実装を決定させます。

http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsDeferred.html#replacement

すべてのバージョンの Ginjector の 1 つのインスタンスは、両方のバージョンのすべてのコードが常にダウンロードされることを意味するため、問題があるように思われます (もちろん、すべてのデスクトップ ビューをモバイル アプリにダウンロードする必要はありません)。

編集: トーマスがコメントで指摘しているように、インジェクターは生成されたクラスであるため、GWT.create() が InjectorServiceXXX である単純なホルダー クラス内に各 InjectorServiceXXX を配置し、交換を使用してホルダーを切り替える必要があります。

于 2011-12-05T09:56:32.193 に答える
1

Ginモジュールで注釈が付けられた共通のインジェクターインターフェースは抽象Ginモジュールを指すことができないため、実際には必要なことを行うのはかなり複雑です。Ginjector インターフェースが指す Gin モジュールは、具象モジュールでなければなりません。具体的なモジュールは、同時に複数の構成を満たすことはできません。

(a) Ginjector インターフェース、たとえば ClientGinjector と、デスクトップ アプリケーション用のモジュール ClientModule を作成します。

(b) 2 番目の Ginjector インターフェイス (ClientGinjectorTablet など) を作成し、(a) で作成したものを拡張しますが、GinModule アノテーションが別のモジュール (ClientModuletablet など) を指すようにします。

-- これで、2 つの Ginjecor インターフェイス (デフォルトのものとタブレット用のセカンダリ インターフェイス) ができました。それぞれが独自の Configure() 実装を持つモジュールを指しています。

(c) ここで、Right Ginjector の実装を取得するための Factory を作成します。これを行うことができるのは、(a) と (b) で気をつけた Ginjector には、(a) で作成されたデフォルトのインターフェースである共通の demonitador があるためです。したがって、次のようなメソッドを使用して抽象 facotry を作成します。 public abstract ClientGinjector getInjector(); 2 つの子具象クラスを作成して、1 つは Desktop/Default Ginjector を取得し、もう 1 つは Tablet Ginjector を取得します。

(d) ここで、モジュールの gwt.xml を構成します。ちょうど youtube の Google IO が説明しているように、Ginjector ファクトリごとに GWT 遅延バインディングを使用して、実行時に目的の facotry を取得する必要があります。

(e) エントリポイントで最初に行うことは、Ginjector を取得するのではなく、GWT 遅延バインディングを使用して Ginjector のファクトリを取得することです。セットの ClientGinjector を返す抽象メソッドを呼び出します。

(f) 叙事詩は最後に失敗します。Guice では、異なるインジェクター (デスクトップ用とタブレット用) を使用している場合でも、同じキー (クラスと注釈) を 2 回バインドすることはできません。同じキーを再定義する 2 つのモジュールがあるとすぐに、キー バインディングの定義はグローバルなようです。それで冒険は終わりです。

于 2012-08-01T15:21:57.227 に答える