Я предполагаю, что вы рассмотрели сторону генерации кода, и сосредоточимся только на том, как мы можем выбрать правильную реализацию в GWT:
но вам все равно придется как-то кормить фабрику текущим контекстом, например. текущая локаль).
Мы могли бы сделать это во время выполнения, как вы предлагаете, но с недавно добавленной поддержкой System.getProperty
вы также можете сделать это во время компиляции.
Первым шагом, конечно же, является создание кода для каждой реализации, к которой вы возможно хотите иметь доступ. Взяв в качестве примера локали, у вас могут быть Foo_en.java
, Foo_es.java
, Foo_de.java
и т. д.
Затем нам нужен согласованный способ получить любую реализацию — возможно, сгенерированный FooFactory
, с помощью такого метода:
public static Foo getFoo(String locale) {
if ("en".equals(locale)) {
return new Foo_en();
} else if /*...
...*/
throw new IllegalArgumentException("Locale " + locale + " is not supported");
}
Если вы спросите пользователя во время runtime, какую локаль он хочет, вы можете передать это значение этому фабричному методу, чтобы получить желаемую реализацию. Точно так же, если бы вы могли прочитать это значение во время выполнения из чего-либо, вы могли бы снова получить правильный экземпляр и продолжить работу.
Но что, если вы действительно хотите, чтобы компилятор выбирал за вас? Давайте сохраним этот код, сгенерированный процессором аннотаций, но перенесем фазу выбора локали на компилятор и его перестановки.
Как и в существующем коде GWT, укажите свойство для языкового стандарта и несколько значений. Затем, вместо того, чтобы спрашивать пользователя или решать во время выполнения в своем собственном Java-коде, какую локаль вы хотите, используйте ту же проводку сценария выбора, которую обычно использует GWT (проверяет URL-адрес, файл cookie, метатеги, сам пользовательский агент и т. д.) - вы можете построить свой собственный property-provider
для этого, если хотите.
Как и прежде, мы можем использовать getFoo(locale)
, но теперь мы используем System.getProperty
для считывания свойства, которое мы создали в нашем файле .gwt.xml. Это будет статически скомпилировано в правильную константу для каждой перестановки. Но вместо того, чтобы вызывать FooFactory.getFoo(System.getProperty("locale"))
каждый раз, когда нам нужен экземпляр, давайте создадим еще один метод в нашей сгенерированной FooFactory:
public static Foo getFoo() {
return getFoo(System.getProperty("locale"));
}
Теперь мы можем просто вызвать FooFactory.getFoo()
, и мы получим правильный класс для нашей текущей перестановки.
Вопрос о кинжале: Thomas, вероятно, гораздо лучше подходит для решения этой проблемы, но нет, Dagger2 не выполняет bind(Foo).to(Bar).in(Scope)
, как это делает Guice, так как это потребует запуска кода для разрешения привязок, в то время как Dagger работает только с тем, что он может видеть, отражая типы, а не запуск кода. Это означает, что вы в конечном итоге получите множество этих методов @Provides или аннотируете свои фактические типы с подробностями о том, что следует использовать для реализации чего.
FWIW до сих пор я не принял Dagger из-за нескольких причуд, которые потребовали бы от меня переосмысления нескольких битов, и я еще не нашел времени, чтобы сделать это переосмысление:
person
Colin Alworth
schedule
29.04.2015