GWT.create()是GWT中的反射等价物,但它只接受类文字,而不是类名的完全限定String.如何使用GWT.create()动态创建带有字符串的类?
根据许多GWT论坛帖子,这是不可能的,但是如何在Rocket-GWT(http://code.google.com/p/rocket-gwt/wiki/Ioc)和Gwittir(http://代码)等框架中完成.google.com/p/gwittir/wiki/Introspection)
虽然很棘手,但这是可能的.以下是血腥的细节:
如果你只把GWT视为JS的直接Java,它就行不通.但是,如果您在编译期间考虑使用GWT编译器Compiles and Executes的Generators - Special类,则可以.因此,您可以在编译时生成java源代码.
我今天有这个需求 - 我们的系统处理服务的动态资源,结束为字符串和类的需要.这是我提出的解决方案 - 顺便说一句,它在托管,IE和Firefox下工作.
创建一个GWT模块声明:
源路径
发电机(其应保持OUTSIDE包中GWT模块源路径的)
接口替换(它将注入Generated类而不是接口)
在该包中,创建一个Marker接口(我称之为Constructable).Generator将查找该Marker
创建一个基本抽象类来保存该工厂.我这样做是为了简化生成的源代码
声明该模块继承在Application.gwt.xml上
一些说明:
理解的关键是围绕发电机的概念;
为了方便起见,Abstract基类派上用场了.
另外,要了解生成的.js源代码名称,甚至是生成的Java源代码
记住Generator输出java文件
GWT.create需要对.class文件的一些引用.您的生成器输出可能会这样做,只要它从您的应用程序以某种方式引用(检查Application.gwt.xml继承您的模块,它也替换了您的Application.gwt.xml声明的生成器的接口)
将GWT.create调用包含在工厂方法/单例内,也包含在GWT.isClient()下
在GWT.runAsync周围包装代码类加载调用是一个非常好的主意,因为它可能需要触发模块加载.这非常重要.
我希望尽快发布源代码.交叉你的手指.:)
布赖恩
问题是GWT.create不知道如何为您的抽象类选择正确的实现
我有新的GWT MVP编码风格的类似问题(参见GWT MVP文档)
我打电话的时候:
ClientFactory clientFactory = GWT.create(ClientFactory.class);
我得到了同样的错误:
延迟绑定结果类型'com.test.mywebapp.client.ClientFactory'不应该是抽象的
我所要做的就是将以下行添加到MyWebapp.gwt.xml文件中:
然后它就像一个魅力
我今天遇到了这个并找到了解决方案.提问者基本上想要编写一个方法,例如:
publicT create(Class clz) { return (T)GWT.create(clz); }
这里MyInterface只是一个标记接口,用于定义我希望能够动态生成的类的范围.如果您尝试编写上述代码,则会出现错误.诀窍是定义一个"实例化器",例如:
public interface Instantiator { publicT create(Class clz); }
现在定义一个返回上述实例的GWT延迟绑定生成器.在生成器中,查询TypeOracle以获取所有类型的MyInterface并为它们生成实现,就像对任何其他类型一样:
例如:
public class InstantiatorGenerator extends Generator { public String generate(...) { TypeOracle typeOracle = context.getTypeOracle(); JClassType myTYpe= typeOracle.findType(MyInterface.class.getName()); JClassType[] types = typeOracle.getTypes(); ListmyInterfaceTypes = Collections.createArrayList(); // Collect all my interface types. for (JClassType type : types) { if (type.isInterface() != null && type.isAssignableTo(myType) && type.equals(myType) == false) { myInterfaceTypes.add(type); } for (JClassType nestedType : type.getNestedTypes()) { if (nestedType.isInterface() != null && nestedType.isAssignableTo(myType) && nestedType.equals(myTYpe) == false) { myInterfaceTypes.add(nestedType); } } } for (JClassType jClassType : myInterfaceTypes) { MyInterfaceGenerator generator = new MyInterfaceGenerator(); generator.generate(logger, context, jClassType.getQualifiedSourceName()); } } // Other instantiator generation code for if () else if () .. constructs as // explained below. }
MyIntefaceGenerator类与任何其他延迟绑定生成器一样.除非您直接在上述生成器中调用它,而不是通过GWT.create.一旦完成MyInterface的所有已知子类型的生成(在生成器中生成MyInterface的子类型时,请确保使类名具有唯一的模式,例如MyInterface.class.getName()+"_ MySpecialImpl") ,通过再次迭代MyInterface的所有已知子类型并创建一堆来简单地创建Instantiator
if (clz.getName().equals(MySpecialDerivativeOfMyInterface)) { return (T) new MySpecialDerivativeOfMyInterface_MySpecialImpl();}
代码风格.最后抛出异常,以便在所有情况下都可以返回一个值.
现在你打电话的地方GWT.create(clz);
改为:
private static final Instantiator instantiator = GWT.create(Instantiator.class); ... return instantiator.create(clz);
另请注意,在GWT模块xml中,您只需为Instantiator定义生成器,而不是为MyInterface生成器定义:
答对了!