我想要创建一个注释处理器来替换对GWT.create的调用。
使用注释处理器,您必须生成两个类,然后(在运行时)根据上下文动态地(在运行时)从中进行选择(您可以生成一个工厂来帮助实现这一点,但是您仍然必须以某种方式向工厂提供当前上下文,例如当前的区域设置)。
资料来源:https://stackoverflow.com/a/29915793/116472
我让我的注释处理器运行,它很好地生成了类。我不知道的部分是运行时选择部分。
如何进行运行时选择?
发布于 2015-04-29 15:35:25
我假设您已经涵盖了代码生成部分,并且只关注如何在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");
}如果您在运行时询问用户需要哪个区域设置,则可以将该值传递给此工厂方法以获得所需的实现。同样,如果您可以在运行时从某个内容读取该值,则可以再次获得正确的实例并继续前进。
但是,如果您真的想让编译器为您选择呢?让我们保留在注释处理器中生成的代码,但是将选择区域设置的阶段移到编译器及其排列。
与现有的GWT代码一样,为locale和几个值指定一个属性。然后,不要在您自己的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(),就可以得到当前排列的正确类。
匕首问题:托马斯很可能更适合解决这个问题,但不,Dagger2不像Guice那样执行bind(Foo).to(Bar).in(Scope),因为这需要运行代码来解析绑定,而Dagger只通过考虑类型来操作,而不是实际运行代码。这意味着您最终会得到许多这样的@Provides方法,或者在实际类型中注释应该使用什么来实现什么。
FWIW到目前为止,我还没有采用Dagger,因为有几个怪癖需要我重新思考一下,而且我还没有花时间重新思考:
发布于 2015-04-29 15:39:53
首先,您没有被迫替换您的GWT.create()调用。因为GWT生成器做了两件事,所以您可能(这并不总是可能)用注释处理器替换代码生成部分,用简单的<replace-with>规则(由注释处理器生成的目标类)替换“选择”部分。
还请注意,GWT.create()实际上在GWT上下文之外可用(例如在服务器端),使用ServerGwtBridge,让我们注册类实例器。注释处理器可以生成这样的实例器,也可以使用反射对其进行编码。
如果您确实想替换您的GWT.create()调用,那么您必须使用一个工厂(直接在调用点,或者包装在一个外观/代理中)。该工厂也可能由注释处理器生成。
与任何这样的工厂一样,代码将是一个if…else级联或switch…case,最终用于new适当的(生成)类;但是条件非常特定于您的需要。
在GWT上下文中,您可以使用GWT.create(UserAgent.class).getCompileTimeValue()访问user.agent绑定属性值,从而将*.gwt.xml的<when-property-is name="user.agent" value"…" />替换为switch…case (请注意,您必须自己处理回退;例如,当没有规则与ie9具体匹配时,ie9回到ie8 )。其他值得注意的值将是LocaleInfo.getCurrentLocale()作为locale绑定属性的替代品(但您的注释处理器不太可能知道该属性的所有可能值,除非您将它们作为选项传递或处理器读取GWT文件--您可能也必须将其名称作为选项传递)。LocaleInfo.getCurrentLocale().isRTL()更有趣。您还可以使用GWT.isClient()或Window.Navigator属性;从GWT2.8开始,您可以使用System.getProperty()访问配置和绑定属性(例如,System.getProperty("user.agent", "unknown"))。最后,当然有JSNI来检测当前浏览器支持的特性;但是,GWT编译器无法优化该代码,所有生成的类都将在最终的JS中编译。
当不能使用这样的静态值时,仍然可以将相关的上下文作为参数传递给工厂。
https://stackoverflow.com/questions/29945548
复制相似问题