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)
ald*_*eal 13
虽然很棘手,但这是可能的.以下是血腥的细节:
如果你只把GWT视为JS的直接Java,它就行不通.但是,如果您在编译期间考虑使用GWT编译器Compiles and Executes的Generators - Special类,则可以.因此,您可以在编译时生成java源代码.
我今天有这个需求 - 我们的系统处理服务的动态资源,结束为字符串和类的需要.这是我提出的解决方案 - 顺便说一句,它在托管,IE和Firefox下工作.
一些说明:
我希望尽快发布源代码.交叉你的手指.:)
布赖恩
问题是GWT.create不知道如何为您的抽象类选择正确的实现
我有新的GWT MVP编码风格的类似问题(参见GWT MVP文档)
我打电话的时候:
ClientFactory clientFactory = GWT.create(ClientFactory.class);
我得到了同样的错误:
延迟绑定结果类型'com.test.mywebapp.client.ClientFactory'不应该是抽象的
我所要做的就是将以下行添加到MyWebapp.gwt.xml文件中:
<!-- Use ClientFactoryImpl by default -->
<replace-with class="com.test.mywebapp.client.ClientFactoryImpl">
<when-type-is class="com.test.mywebapp.client.ClientFactory"/>
</replace-with>
Run Code Online (Sandbox Code Playgroud)
然后它就像一个魅力
我今天遇到了这个并找到了解决方案.提问者基本上想要编写一个方法,例如:
public <T extends MyInterface> T create(Class<T> clz) {
return (T)GWT.create(clz);
}
Run Code Online (Sandbox Code Playgroud)
这里MyInterface只是一个标记接口,用于定义我希望能够动态生成的类的范围.如果您尝试编写上述代码,则会出现错误.诀窍是定义一个"实例化器",例如:
public interface Instantiator {
public <T extends MyInterface> T create(Class<T> clz);
}
Run Code Online (Sandbox Code Playgroud)
现在定义一个返回上述实例的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();
List<JClassType> myInterfaceTypes = 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.
}
Run Code Online (Sandbox Code Playgroud)
MyIntefaceGenerator类与任何其他延迟绑定生成器一样.除非您直接在上述生成器中调用它,而不是通过GWT.create.一旦完成MyInterface的所有已知子类型的生成(在生成器中生成MyInterface的子类型时,请确保使类名具有唯一的模式,例如MyInterface.class.getName()+"_ MySpecialImpl") ,通过再次迭代MyInterface的所有已知子类型并创建一堆来简单地创建Instantiator
if (clz.getName().equals(MySpecialDerivativeOfMyInterface)) { return (T) new MySpecialDerivativeOfMyInterface_MySpecialImpl();}
Run Code Online (Sandbox Code Playgroud)
代码风格.最后抛出异常,以便在所有情况下都可以返回一个值.
现在你打电话的地方GWT.create(clz);
改为:
private static final Instantiator instantiator = GWT.create(Instantiator.class);
...
return instantiator.create(clz);
Run Code Online (Sandbox Code Playgroud)
另请注意,在GWT模块xml中,您只需为Instantiator定义生成器,而不是为MyInterface生成器定义:
<generate-with class="package.rebind.InstantiatorGenerator">
<when-type-assignable class="package.impl.Instantiator" />
</generate-with>
Run Code Online (Sandbox Code Playgroud)
答对了!
没有查看 Rocket/gwittir 的代码(如果你想知道他们是如何做到的,你应该这样做,毕竟它是开源的),我只能猜测他们在编译期间采用了延迟绑定然后,他们计算出对反射的所有调用,并静态生成实现这些调用所需的所有代码。所以在运行时,你不能做不同的事情。