Guice

2010-09-25 27 views
12

Aşağıdaki kod bir jenerik fabrika enjekte bir Foo<T> verilen Bar<T> üreten bir fabrikanın bir örnektir. her tür T için, bir Foo<T> bir Bar<T> yapabilirsiniz: fabrika T ne olduğunu umursamıyor. Ben kodu çalıştırdığınızdaGuice

import com.google.inject.*; 
import com.google.inject.assistedinject.*; 

class Foo<T> { 
    public void flip(T x) { System.out.println("flip: " + x); } 
} 

interface Bar<T> { 
    void flipflop(T x); 
} 

class BarImpl<T> implements Bar<T> { 
    Foo<T> foo; 

    @Inject 
    BarImpl(Foo<T> foo) { this.foo = foo; } 

    public void flipflop(T x) { foo.flip(x); System.out.println("flop: " + x); } 
} 

interface BarFactory { 
    <T> Bar<T> create(Foo<T> f); 
} 

class Module extends AbstractModule { 
    public void configure() { 
    bind(BarFactory.class) 
     .toProvider( 
      FactoryProvider.newFactory(BarFactory.class, BarImpl.class) 
        ); 
    } 
} 

public class GenericInject { 
    public static void main(String[] args) { 
    Injector injector = Guice.createInjector(new Module()); 

    Foo<Integer> foo = new Foo<Integer>(); 
    Bar<Integer> bar = injector.getInstance(BarFactory.class).create(foo); 
    bar.flipflop(0); 
    } 
} 

, ben Guice aşağıdaki hataları alıyorum: Ben Guice belgelerinde jenerik bulabileceğiniz

1) No implementation for BarFactory was bound. 
    at Module.configure(GenericInject.java:38) 

2) Bar<T> cannot be used as a key; It is not fully specified. 

tek referans bir TypeLiteral kullanmak söylüyor. Ama bende bir tür yok, ben fabrika ile ilgili olmayan genel bir yer tutucu var. Herhangi bir ipucu?

cevap

-1

sen bahar benzer kablolama sistemi olarak Guice düşünürseniz, o zaman gerçekten bir jenerik örneği tel için bir anlam ifade etmiyor. Anahtarlara belirli örneklerle bağlantı kurarsınız. Böylece, başka bir örnek sınıf, @BuilderFactory ile bir şeyi işaretlediğinde, belirli oluşturulan örneği alırsınız.

uygulamanız jenerik olduğundan, belirli bir örneğini enjekte etmek yeterli bilgi girmediniz. Fabrika üreticisi kullanmama rağmen, benim varsayımım, Barfactory'yi tamamen parametreli bir örneğe bağlamanız gerektiğidir. BarImpl yerine BarImpl<Concrete>

BarFactory.class'ı bağladığınızdan beri, birden çok örneği bağlamak istiyorsanız, bir şekilde adıyla bir şeye çarpmanız gerekir (sözdizimini kontrol etmediyseniz, ama)

bind(BarFactory.class).annotatedWith(Names.named("name1")) 
     .toProvider( 

or by generics, bind(BarFactory<Concrete>).toProvider... 
+1

BarFactory jenerik değildir, bu yüzden o ben kablolu ettik yolu tel için çok mantıklı. Barın parametreli bir örneği, sözleşme ile eşleşmiyordu: bir Foo almak ve herhangi bir için bir Bar döndürmek için gereksinimler oluşturun. –

4

bir seçenek sadece elle BarFactory klişe yazmaktır:

class BarImplFactory implements BarFactory { 
    public <T> Bar<T> create(Foo<T> f) { 
    return new BarImpl(f); 
    } 
} 

bağlayıcı

olur 0
+0

Guicer, BarImpl öğesinin yapıcısını açık bir şekilde çağrılmasa bile diğer yapıcı parametrelerini enjekte edecektir. Guice? –

+1

Hayır, sanmıyorum. Yine de kendi Foos'unuzu sağlamanız gerekecektir. –

+2

@Jeff Axelrod, Önce BarImplFactory yapıcısına enjekte ve sonra bu değerleri kopyalayarak BarImpl diğer yapıcı params enjekte edebilir. – Shuo

İlgili konular