2016-08-31 8 views
0

誰かがThingを求めたら、私は彼らにLegacyThingを与えたいと思います。しかし、もし彼らが@Modern Thingを求めるなら、私は彼らにThingを与えたいと思っています。Guice:他にバインドされている実装タイプにバインドしますか?

これは動作しません:

bind(Thing.class).to(LegacyThing.class); 
bind(Thing.class).annotatedWith(Modern.class).to(Thing.class); 

代わりに直接Thingへの、第一の結合への第二の結合のリンクからです。

別のバインドへのリンクではなく、実装としてThingにバインドするにはどうすればよいですか。

Thingをインスタンス化する必要はありません。なぜなら、インジェクタに対処する必要がある依存関係がたくさんあるからです。私はむしろそれをサブクラス化したり、そこからインターフェイスを抽出したりすることもありません。

私が作ってみた最高のアイデアは、バインディングのコンストラクタを使用することですが、それはハック感じ:

bind(Thing.class) 
    .annotatedWith(Modern.class) 
    .toConstructor((Constructor<Thing>) InjectionPoint.forConstructorOf(Thing.class) 
                 .getMember()); 
+0

あなたのアプローチはかなり(カスタム悪いです 'Provider'を、使用することを除いて)動作する唯一の方法です。 –

+1

もう一つのアプローチは、 'Thing'が抽象的で、' LegacyThing'と 'ModernThing'サブクラスを持つようにリファクタリングすることです。 –

答えて

0

あなたがそうするようにメソッドプロバイダを使用することができます。あなたは自分自身でインスタンスを作成したくないと言っていますが、super()LegacyThingに呼び出したときには、すでに難しい仕事をしています。ちょうどコピー/貼り付け。または、フィールドを直接挿入します。

import com.google.inject.*; 

import java.lang.annotation.*; 

public class Test { 

    static class Dependency {} 
    static class Thing { 
    @Inject Thing(Dependency dependency) {} 
    } 
    static class LegacyThing extends Thing { 
    @Inject LegacyThing(Dependency dependency) { super(dependency); } 
    } 
    static class Holder { 
    @Inject @Modern Thing modern; 
    @Inject Thing legacy; 
    } 

    @BindingAnnotation 
    @Retention(RetentionPolicy.RUNTIME) 
    @Target({ElementType.FIELD, ElementType.METHOD}) 
    static @interface Modern { } 

    public static void main(String[] args) { 
    Holder holder = Guice.createInjector(new AbstractModule() { 
     @Provides @Modern Thing provideModernThing(Dependency dependency) { 
     return new Thing(dependency); 
     } 
     @Provides Thing provideLegacyThing(Dependency dependency) { 
     return new LegacyThing(dependency); 
     } 
     @Override protected void configure() { 
     bind(Dependency.class).in(Singleton.class); 
     } 
    }).getInstance(Holder.class); 
    System.out.printf("Modern: %s%n", holder.modern.getClass().getName()); 
    System.out.printf("Legacy: %s%n", holder.legacy.getClass().getName()); 
    } 
} 

結果:

Modern: Test$Thing 
Legacy: Test$LegacyThing 
関連する問題