創建從類名新實例有一個類int以下名稱com.test.TestClass
我如何在GWT
在我的代碼一點我有隻具有類名稱的字符串獲得這個類的實例。我曾嘗試使用GWT.create()
但它只能在開發模式下工作。任何人都可以告訴我如何從類名獲得gwt中的實例。
創建從類名新實例有一個類int以下名稱com.test.TestClass
我如何在GWT
在我的代碼一點我有隻具有類名稱的字符串獲得這個類的實例。我曾嘗試使用GWT.create()
但它只能在開發模式下工作。任何人都可以告訴我如何從類名獲得gwt中的實例。
由於反射在客戶端是不可能的,因此您必須模擬反射的唯一解決方案是使用延遲綁定。
使用延遲綁定在編譯期間發現您希望用類名實例化的所有類。您可以在所有這些類上使用標記接口來幫助TypeOracle識別這些類。您可以動態生成一個工廠類,它接收該類的簡單名稱並返回該類的新實例化對象。這個方法非常簡單,你可以在谷歌的教程中找到關於延遲綁定的一個很好的解釋。
編輯: - 一些骨架代碼讓你開始。 (剝離下來的我的生產代碼版本,爲您在生成文件編譯器錯誤!和調試流程)
首先>添加下面的Blurb到您的* .gwt.xml,以使編譯器調用我們的com.package.ReflectionGenerator,它將生成一個簡單的工廠類來模仿客戶端的反射。
<generate-with class="com.package.ReflectionGenerator">
<when-type-assignable class="com.package.client.Reflection" />
</generate-with>
下一頁>定義的接口爲我們的工廠類
public interface Reflection {
public <T, V extends T> T instantiate(Class<V> clazz);
}
末>實施ReflectionGenerator
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
public class ReflectionGenerator extends Generator
{
@Override
public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException
{
TypeOracle oracle = context.getTypeOracle();
JClassType instantiableType = oracle.findType(MarkerInterface.class.getName());
List<JClassType> clazzes = new ArrayList<JClassType>();
PropertyOracle propertyOracle = context.getPropertyOracle();
for (JClassType classType : oracle.getTypes())
{
if (!classType.equals(instantiableType) && classType.isAssignableTo(instantiableType))
clazzes.add(classType);
}
final String genPackageName = "com.package.client";
final String genClassName = "ReflectionImpl";
ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(genPackageName, genClassName);
composer.addImplementedInterface(Reflection.class.getCanonicalName());
composer.addImport("com.package.client.*");
PrintWriter printWriter = context.tryCreate(logger, genPackageName, genClassName);
if (printWriter != null)
{
SourceWriter sourceWriter = composer.createSourceWriter(context, printWriter);
sourceWriter.println("ReflectionImpl() {");
sourceWriter.println("}");
printFactoryMethod(clazzes, sourceWriter);
sourceWriter.commit(logger);
}
return composer.getCreatedClassName();
}
private void printFactoryMethod(List<JClassType> clazzes, SourceWriter sourceWriter)
{
sourceWriter.println();
sourceWriter.println("public <T, V extends T> T instantiate(Class<V> clazz) {");
for (JClassType classType : clazzes)
{
if (classType.isAbstract())
continue;
sourceWriter.println();
sourceWriter.indent();
sourceWriter.println("if (clazz.getName().endsWith(\"." + classType.getName() + "\")) {");
sourceWriter.indent();
sourceWriter.println("return (T) new " + classType.getQualifiedSourceName() + "();");
sourceWriter.outdent();
sourceWriter.println("}");
sourceWriter.outdent();
sourceWriter.println();
}
sourceWriter.indent();
sourceWriter.println("return (T) null;");
sourceWriter.outdent();
sourceWriter.println();
sourceWriter.println("}");
sourceWriter.outdent();
sourceWriter.println();
}
}
這應該會在您的工作空間工廠類ReflectionGenerator,檢查生成的文件並調整源代碼編寫器以生成co你想要什麼。
用法GWT.create(Reflection.class).instantiate(YourClass.class);
我已經使用一個標記接口'MarkerInterface'
在發電機以限制由工廠支持的類的數量,因此,其結果是所有參與的類必須實現'MarkerInterface'
非常感謝。如果您可以發佈示例代碼,它對我和其他用戶都非常有用。 – DonX 2010-07-05 12:01:58
我編輯了我的回覆帖子,展示了使用綁定的骨架代碼。請通過,如果偶然發生編譯錯誤或兩次錯誤,請原諒我,我沒有通過編譯器運行代碼。我太懶了:P – 2010-07-12 10:17:07
GWT。創建(Reflection.class).instantiate(YourClass.class);
爲什麼你不使用,然後只是GWT.create(YourClass.class);
?
也許你換貨GWT.create(Reflection.class).instantiate("YourClass");
這裏是很好的測試,評價和阿斯溫帕布代碼稍微重構版本:
使用示例:
String targetEntryPointClass = "my.code.client.Sample3";
ClassFromStringFactory classFromStringFactory = GWT.create(ClassFromStringFactory.class);
Object targetEntryPointInstance = classFromStringFactory.instantiate(targetEntryPointClass);
if (targetEntryPointInstance == null) {
// throw some exception
}
if (targetEntryPointInstance instanceof EntryPoint) {
((EntryPoint) targetEntryPointInstance).onModuleLoad();
} else {
// throw some exception
}
在我的項目中,我使用GWT自己的EntryPoint作爲標記界面。這使我能夠通過URL運行任意的EntryPoint:http://localhost:8080/my.code.client.Sample3
; Dispatcher EntryPoint通過我的ClassFromStringFactory
實例化my.code.client.Sample3
。只有調度程序入口點在GWT模塊描述符和延遲綁定中配置,其他一切都是動態的。
對於好奇,這裏是GWT(用於生產模式代碼服務器在DevMode的或編譯器)生成我ClassFromStringFactoryImpl的內容:
package my.code.client.reflection;
public class ClassFromStringFactoryImpl implements ClassFromStringFactory {
public ClassFromStringFactoryImpl() {}
public Object instantiate(String className) {
if (className == null) {
return null
}
else if (className.equals("my.code.client.Sample1")) {
return new my.code.client.Sample1();
}
else if (className.equals("my.code.client.Sample2")) {
return new my.code.client.Sample2();
}
..and so on, 3 same lines per every supported type
return null;
}
}
在這樣的臨時文件:C:\Users\espinosa\AppData\Local\Temp\my.code.client.reflection.ClassFromStringFactoryImpl4245548251877324156.java
。 注:正如你可以看到這個文件只產生失敗的情況下,不會對編譯成功
,就沒有真正的反省。延遲綁定不會有任何特殊的魔法。 類似的Java代碼可以由Velocity模板生成,作爲Maven構建的一部分或者特殊工具,如XText,APT-Jelly。使用GWT的發生器只是一個方便。
限制「受支持」類的數量是很重要的,否則生成的ClassFromStringFactoryImpl
將會太大,實際上太大或甚至超過Java類的限制。某些過濾是必要的,標記接口只是一個選項,其他標記則標記註釋(請參閱GWT的JClassType#getAnnotation(Class))或僅選擇包。無論如何,通過這個「反射」來確保支持的類的數量不會超過數百個。
非常感謝Ashwin Prabhu爲我指出了正確的方向。
看起來像一個副本http://stackoverflow.com/questions/451658/gwt-dynamic-loading-using-gwt-create-with-string-literals-instead-of-class-lite – 2010-06-14 03:58:00
Thanks.I am也期待相同。 – DonX 2010-06-14 04:03:54