2011-12-04 11 views
7

Mam webapp, który używa GIN do wstrzykiwania zależności w punkcie wejścia.Guice/Gin. Jak wstrzyknąć wiele implementacji

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); 
    } 
} 

muszę mobilną wersję, że używają różnych implementacji RootView. Zależności są opisane w następujący moduł

public class RootViewMobileInject extends AbstractGinModule { 

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

Pytanie brzmi, jak wybrać potrzebną zależność warunkowo czy musimy wersję mobilną lub domyślną. Widziałem GWT-GIN Multiple Implementations, ale nie doszedłem do tego rozwiązania, ponieważ dostawca zrywa łańcuch zależności, a wzór fabryczny ulega awarii. W "Big Modular Java with guice" wideo here (12 minute) Wtryskiwacz Guice z modułami został przedstawiony jako zamiennik dla fabryk. Więc moim pytaniem jest, czy powinienem stworzyć różne Ginjector dla wersji mobilnych i domyślnych (jak MobileFactory i DefaultFactory) mojej aplikacji, czy byłoby to złe praktyki i powinienem skonfigurować jedną instancję Ginjectora ze wszystkimi potrzebnymi wersjami. Na przykład z powiązaniami adnotacji w ten sposób.

public class RootViewMobileInject extends AbstractGinModule { 

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

i odnotowany wykorzystują @Mobile GWT wiązanie w punkcie wejścia

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

w taki uproszczony przykład jak wyżej to może okazać się niemożliwe. Ale jeśli aplikacja ma więcej zależności, które wymagają wersji mobilnej i domyślnej. Wygląda na to, że wracamy do niepotwierdzonego "brzydkiego" (jak mówiono w prezentacji Guice) fabryk. Przepraszamy za mój angielski. Każda pomoc jest doceniana.

+1

Chciałem tylko dodać, że pomysł tutaj i rozwiązanie z @aldanok mogą być również używane do specyficznego dostosowania klienta w aplikacji. Specyficzne dla klienta: gwt.xml + moduł gin + implementacje interfejsu. – MeTTeO

Odpowiedz

9

Uważam, że będziesz chciał użyć odroczonego wiązania GWT, używając wymiany klas, aby powiązać inną wersję InjectorService w zależności od klienta użytkownika. Zapewni to, że wersja mobilna ma tylko implementacje mobilne skompilowane w (i pobrane)

Tak więc masz InjectorServiceDesktop, InjectorServiceMobile, które zarówno rozszerzają się z InjectorService, a następnie GWT.create (InjectorService.class), i pozwalają odroczyć wiązanie decydować którą implementację powinien użyć.

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

Jedna instancja Ginjector ze wszystkimi wersjami wydaje się złe, jak to oznacza cały kod dla obu wersji jest zawsze pobierany (a na pewno nie chcesz, aby pobrać wszystkie swoje poglądy pulpitu do aplikacji mobilnej)

EDYCJA: Jak Thomas wskazuje w komentarzach, ponieważ wtryskiwacze są generowanymi klasami, musisz umieścić każdy InjectorServiceXXX wewnątrz prostej klasy uchwytów, która GWT.create() jest InjectorServiceXXX, i użyć zamiennika, aby przełączać się między posiadacze.

+5

+1, z tym wyjątkiem, że nie będzie działać tak: nie możesz mieć zastępowania i generowania w tym samym czasie, musisz utworzyć "InjectorServiceHolder" z 2 podklasami. Każdy "GWT.create()" jest innym podrzędnym interfejsem "InjectorService". Używasz zamiennika na "uchwycie", aby wybrać, której 'InjectorService' użyć, a' GWT.create() 'na podinterfejsie' InjectorService' uruchomi generowanie kodu GIN. –

+0

okrzyki za korektę! zaktualizował odpowiedź. – aidanok

+0

Dziękuję za odpowiedź. Raczej się z tobą zgadzam, że powinienem użyć różnych Ginjectorów. jest bardzo prosty i wygodny. Ale co masz zrobić z tym samym problemem po stronie Guice, który nie ma techniki odroczonego wiązania. Jaką technikę chciałbyś zastąpić modułem podstawowym - [Modules.override] (http://stackoverflow.com/questions/7314323/how-to-override- bind-in -gin) lub po prostu dziedziczeniem Java. Czemu? I więcej ... jak skonfigurować Ginjector/Injector, gdy wszystkie wersje są potrzebne (powiedzmy DefaultView i LoggedInView)? – trupanka

1

Wykonanie tego, co chcesz, jest w rzeczywistości dość skomplikowane, ponieważ twój wspólny interfejs wtryskiwaczy, który jest opisany za pomocą twojego modułu Gin, nie może wskazywać na abstrakcyjny moduł Gin. Moduł Gin wskazany przez twój interfejs Ginjector musi być konkretny. Moduł betonowy nie może jednocześnie spełniać wielu konfiguracji.

Co należy zrobić: (a) Utwórz interfejs Ginjector, na przykład ClientGinjector i moduł ClientModule, dla aplikacji komputerowej.

(b) Utwórz drugi interfejs Ginjector, na przykład ClientGinjectorTablet, rozszerzając ten, który został utworzony w (a), ale z adnotacją GinModule wskazującą na inny moduł, na przykład ClientModuletablet.

- Masz teraz dwa interfejsy Ginjecor, domyślny i wtórny dla tabletów, z których każdy wskazuje na moduł z własnymi implementacjami Configure().

(c) Teraz chcesz utworzyć Factory, aby uzyskać prawidłową implementację Ginjector. Możesz to zrobić, ponieważ Ginjector, którym się opiekujesz (a) i (b) ma wspólnego demonitadora, który jest domyślnym interfejsem stworzonym w (a). Tworzysz więc abstrakcyjną maszynę obliczeniową za pomocą metody takiej jak ta: public abstract ClientGinjector getInjector(); Tworzysz dwoje dzieci, konkretne klasy One, aby uzyskać Desktop/Default Ginjector, a jeszcze inny, aby uzyskać Ginjector Tablet.

(d) Teraz skonfiguruj gwt.xml swojego modułu tak, jak Google IO na youtube wyjaśnia, że ​​powinieneś uzyskać żądaną maszynę obliczeniową w czasie wykonywania, używając odroczonych wiązań GWT dla każdej fabryki Ginjector.

(e) W punkcie początkowym nie można uzyskać Ginjectora, ale fabryka dla Ginjectors używającego odroczonego wiązania GWT. Wywołujesz abstrakcyjną metodę, która zwraca ClientGinjector, twój zestaw.

(f) Epickie niepowodzenie na końcu. Guice nie pozwoli ci związać dwa razy tego samego klucza (klasa plus adnotacja), nawet jeśli będziesz używał różnych wtryskiwaczy (jeden na biurko, a drugi na tablet). Wydaje się, że kluczowe definicje wiążące są globalne, gdy tylko masz dwa moduły definiujące ponownie te same klucze, to koniec przygody.