2011-07-08 7 views
6

私はこのGuiceのロボット脚の例に非常に似ています。したがって、私はロボット足の例に必要な注釈を使用することはできません。Guiceのロボット脚の例をMultibindingで一般化する

GuiceのMultibindings拡張を使用してjava.util.Setでこれらのすべての「足」を集めることが期待されます。

技術的には、PrivateModuleでは、実装を、Multibindings拡張機能によって提供されるセットの要素として直接公開したいと考えています。私はちょうどそれを行う方法を知らない。リファレンスとコードたとえば

、ここではロボットの足の例を参照してください。http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_do_I_build_two_similar_but_slightly_different_trees_of_objec


ここでは私の正確なユースケースです:

私は、次のしている:

// Main application 
public interface MyTree {...} 
public interface MyInterface { 
    public MyTree getMyTree() {} 
} 
public abstract class MyModule extends PrivateModule {} 
public class MyManager { 
    @Inject MyManager (Set<MyInterface> interfaces){ this.interfaces = interfaces } 
} 
public class MainModule extends AbstractModule { 
    public void configure() { 
    // Install all MyModules using java.util.ServiceLoader. 
    } 
} 


// In expansion "square.jar" 
public class SquareTree implements MyTree {...} 
public class SquareImplementation implements MyInterface { 
    @Inject SquareImplementation (MyTree tree) { this.tree = tree; } 
    public MyTree getMyTree() { return this.tree; } 
} 
public class SquareModule extends MyModule { // correctly defined as a ServiceLoader's service. 
    public void configure() { 
    // How to make this public IN a multibinder's set? 
    bind(MyInterface.class).to(SquareImplementation.class); 

    // Implementation specific to the Squareimplementation. 
    bind(MyTree.class).to(SquareTree.class); 
    } 
} 

// In expansion "circle.jar" 
public class CircleTree implements MyTree {...} 
public class CircleImplementation implements MyInterface { 
    @Inject CircleImplementation (MyTree tree) { this.tree = tree; } 
    public MyTree getMyTree() { return this.tree; } 
} 
public class CircleModule extends MyModule { // correctly defined as a ServiceLoader's service. 
    public void configure() { 
    // How to make this public IN a multibinder's set? 
    bind(MyInterface.class).to(CircleImplementation.class); 

    // Implementation specific to the Circle implementation. 
    bind(MyTree.class).to(CircleTree.class); 
    } 
} 

ので、私は拡張ジャーについて話していますが、最初はそれらを知らないので、どれくらいのものが存在するか分かりません。MyModuleにをロードする必要がありますと各モジュールはMyInterfaceの実装を定義する必要があります(これら2つの部分は問題ありません)。

問題はすべてMyInterfaceの実装を1つのセット(MyManager)で取得することです。どうやってやるの?これは、MyModuleというは拡張するインタフェースであるなら、私はPrivateModuleを拡張するのではなく、任意のモジュールの実装を使用するには、「顧客」を強制しないことを可能にする

// Create the set binder. 
Multibinder<MyInterface> interfaceBinder = Multibinder.newSetBinder(binder(), MyInterface.class, MyBinding.class); 

// Load each module that is defined as a service. 
for (final MyModule module : ServiceLoader.load(MyModule.class)) { 

    // Generate a key with a unique random name, so it doesn't interfere with other bindings. 
    final Key<MyInterface> myKey = Key.get(MyInterface.class, Names.named(UUID.randomUUID().toString())); 
    install(new PrivateModule() { 
    @Override protected void configure() { 
     // Install the module as part of a PrivateModule so they have full hands on their own implementation. 
     install(module); 
     // Bind the unique named key to the binding of MyInterface. 
     bind(myKey).to(MyInterface.class); 
     // Expose the unique named binding 
     expose(myKey); 
    } 
    }); 
    // bind the unique named binding to the set 
    interfaceBinder.addBinding().to(myKey); 
} 


ソリューション、完全にジェシーの回答に基づいてモジュール。

答えて

9

プライベートモジュールからのバインディングを宣伝して、トップレベルのインジェクタのマルチバインディングにすることができるように、いくつかのフープを飛び越える必要があるようです。

これは動作するはずです:

public class SquareModule extends AbstractModule { // does not extend PrivateModule 
    @Overide public void configure() { 
    // this key is unique; each module needs its own! 
    final Key<MyInterface> keyToExpose 
     = Key.get(MyInterface.class, Names.named("square")); 

    install(new PrivateModule() { 
     @Override public void configure() { 

     // Your private bindings go here, including the binding for MyInterface. 
     // You can install other modules here as well! 
     ... 

     // expose the MyInterface binding with the unique key 
     bind(keyToExpose).to(MyInterface.class); 
     expose(keyToExpose); 
     } 
    }); 

    // add the exposed unique key to the multibinding 
    Multibinder.newSetBinder(binder(), MyInterface.class).addBinding().to(keyToExpose); 
    } 
} 

multibindingsはトップレベルのインジェクターで発生する必要があるため、この回避策が必要です。しかし、プライベートモジュールバインディングはそのインジェクタには見えないので、それらを公開する必要があります。

+0

ありがとうございました。あなたの答えを読んだ後、私は問題を正しく説明しているかどうか確信がありませんでした。だから私は一例で私の質問を修正した。これは今より理解できますか? –

+0

あなたの新しい答えをテストし、結果をここで報告します。 –

+0

はい、完全に動作します。モジュール化するのはかなり難しいですが、問題ありません。 –

関連する問題