W tym pytaniu mówię o Dagger2. Dagger2 składa się głównie ze składników i modułów. Oto przykład:Opóźnione wiązanie z Dagger2 Wykres za pomocą przetwarzania opisów
Załóżmy Mam interfejs:
public interface MyCoolService {
void run();
}
i ewentualnego wdrożenia:
public class MyCoolServiceImpl {
@Override
void run() {}
}
mogę połączyć realizację z interfejsem wykorzystaniem Dagger2 prądotwórcze:
@Component(modules = {MyModule.class})
@Singleton
public interface Component {
MyCoolService getMyCoolService();
}
i
@Module
public class MyModule {
@Provides @Singleton
MyCoolService provideMyCoolService() {
return new MyCoolServiceImpl();
}
}
To było krótkie wprowadzenie do Dagger2. Załóżmy teraz, mam następujący interfejs:
public interface MySecondCoolService {
void doCoolStuff();
}
Nie ma realizacja MySecondCoolServiceImpl
z MySecondCoolService
w kodzie. Zamiast tego mam Annotations @JustForCoolStuff
do oznaczania pól i metod. Stworzyłem procesor adnotacji, który zbiera wszystkie te adnotacje i generuje MySecondCoolServiceImpl
, który implementuje MySecondCoolService
. Kompilator zna nowy interfejs MySecondCoolService
przed uruchomieniem procesora adnotacji. Więc mogę zmienić mój komponent jako:
@Component(modules = {MyModule.class})
@Singleton
public interface Component {
MyCoolService getMyCoolService();
MySecondCoolService getMySecondCoolService();
}
problemem jest to, że nie mam jeszcze implementacji w kodzie i nie wiem nazwę realizacji MySecondCoolService
który zostanie wygenerowany przez procesor adnotacji . Dlatego nie mogę połączyć interfejsu z poprawną implementacją w MyModule
. Jedyne, co mogę zrobić, to zmienić procesor adnotacji tak, aby generował dla mnie nowy moduł. Mojego procesora adnotacji może wygenerować moduł (MyGeneratedModule
), jak poniżej:
@Module
public class MyGeneratedModule {
@Provides @Singleton
MySecondCoolService provide MySecondCoolService() {
return new MySecondCoolServiceImpl();
}
}
Ponownie MyGeneratedModule
generowanego przez procesor opisów. Nie mam do niego dostępu przed uruchomieniem procesora adnotacji, ale nie znam nazwy.
Tutaj jest problem: Procesor adnotacji musi jakoś powiedzieć Dagger2, że istnieje nowy moduł, który Dagger2 powinien wziąć pod uwagę. Ponieważ procesory adnotacji nie może zmieniać plików nie może przedłużyć @Component(modules = {MyModule.class})
adnotacji i zmienić go w coś takiego: @Component(modules = {MyModule.class, MyGeneratedModule.class})
Czy istnieje sposób, aby dodać MyGeneratedModule
programowo do wykresu zależności dagger2? W jaki sposób mój procesor adnotacji może powiedzieć Daggerowi2, że powinno być nowe połączenie między interfejsem a implementacją, tak jak to opisałem powyżej?
Foray: wiem, że coś takiego można zrobić w Google Guice i Google Gin. Projekt, który to robi GWTP.Nie masz prezentera:
public class StartPagePresenter extends ... {
@NameToken("start")
public interface MyProxy extends ProxyPlace<StartPagePresenter> {
}
...
}
który ma @NameToken
adnotacji do interfejsu ProxyPlace
. W twojej AbstractPresenterModule
okablować widok z prezenterem i pełnomocnika:
public class ApplicationModule extends AbstractPresenterModule {
bindPresenter(StartPagePresenter.class,
StartPagePresenter.MyView.class, StartPageView.class,
StartPagePresenter.MyProxy.class);
...
}
Jak więc widać żadnej implementacji interfejsu MyProxy
wypowiedzenia. Implementacja stworzona przez Generator (podobna do procesora adnotacji, ale dla GWT). Nie Generator generuje realizacja StartPagePresenter.MyProxy
i dodać je do systemu guide/gin:
public class StartPagePresenterMyProxyImpl extends com.gwtplatform.mvp.client.proxy.ProxyPlaceImpl<StartPagePresenter> implements buddyis.mobile.client.app.start.StartPagePresenter.MyProxy, com.gwtplatform.mvp.client.DelayedBind {
private com.gwtplatform.mvp.client.ClientGinjector ginjector;
@Override
public void delayedBind(Ginjector baseGinjector) {
ginjector = (com.gwtplatform.mvp.client.ClientGinjector)baseGinjector;
bind(ginjector.getPlaceManager(),
ginjector.getEventBus());
presenter = new CodeSplitProvider<StartPagePresenter>(ginjector.getbuddyismobileclientappstartStartPagePresenter());
...
}
}
Dlaczego nie można po prostu napisać '@Component (moduły = {MyModule.class, MyGeneratedModule.class})' w swojej kod? –
@TavianBarnes Jak napisałem w tekście, nie znam nazwy '' MyGeneratedModule'', która zostanie utworzona. –
Jeśli masz procesor adnotacji generujący klasę, której nazwiska nie znasz z góry, i nie ma innej możliwości jej utworzenia, oznacza to, że masz problem. Najpierw załatw to, reszta przyjdzie. Nieważne, czy użyjesz Sztyletu, czy nie. –