如何在gwt的类名中创建新的实例 [英] How to create new instance from class name in gwt

查看:116
本文介绍了如何在gwt的类名中创建新的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类int以下名称 com.test.TestClass



在我的代码中的某一点我必须通过只有类名字符串来获得此类的实例。我曾尝试使用 GWT.create()
但它只能在开发模式下工作。任何人都可以告诉我如何从类名获得gwt中的实例。

解决方案

由于反射在客户端不可行,因此您必须模拟反射的唯一解决方案是使用延迟绑定。

使用延迟绑定在编译期间发现所有您希望用类名实例化的类。您可以在所有这些类上使用标记接口来帮助TypeOracle识别这些类。您可以动态生成一个工厂类,它接收该类的简单名称并返回该类的新实例化对象。这个方法非常简单,你可以在谷歌的教程中找到关于延迟绑定的一个很好的解释。

编辑:
一些骨架代码让你开始。 (剥离我的产品代码版本,检查生成的文件中的编译器错误并调试流程)

<为了让编译器调用我们的com.package.ReflectionGenerator,它将生成一个简单的工厂类,以模仿客户端的反射,将下面的blurb添加到* .gwt.xml中。 。

 < 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实例化(Class< V> clazz);
}

Last> 实现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;
导入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;
$ b $ 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());

列表< JClassType> clazzes = new ArrayList< JClassType>();

PropertyOracle propertyOracle = context.getPropertyOracle(); (JClassType classType:oracle.getTypes())

if(!classType.equals(instantiableType)&& classType.isAssignableTo(instantiableType))
clazzes.add(classType);
}

最终字符串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();

$ b $ private void printFactoryMethod(List< JClassType> clazzes,SourceWriter sourceWriter)
{
sourceWriter.println();

sourceWriter.println(public< T,V extends T> T instantiate(Class< V> clazz){); (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,检查生成的文件并调整源代码编写器代码以生成您想要的代码。

用法 GWT.create(Reflection.class).instantiate(YourClass.class);



我在生成器中使用了一个标记接口'MarkerInterface'来限制工厂支持的类的数量,因此结果所有参与的类必须实现'MarkerInterface'


I have a class int the following name com.test.TestClass

At one point in my code I have to get instance of this class by only having the class name string. I have tried using GWT.create() But it is working only in dev mode. Can any one tell me how to get instance in gwt from class name.

解决方案

Since reflection is not possible on the client side, the only solution you have to mimic reflection is using deferred binding.

Use deferred binding to discover all classes you wish to instantiate with the class name during compile time. You may use a marker interface on all such classes to aid TypeOracle to identify these. You dynamically generate a factory class, which takes in the simple name of the class and returns a newly instantiated object of that class. The approach is very straight forward and you will find a good explanation of deferred binding in google's tutorials to boot.

Edit:- Some skeletal code to get you started. (Stripped down version of my production code, check for compiler errors in the generated file! and debug the flow)

First> Add the following blurb into your *.gwt.xml, to so that the compiler invokes our com.package.ReflectionGenerator, which will generate a simple factory class to mimic reflection on the client side.

  <generate-with class="com.package.ReflectionGenerator">
      <when-type-assignable class="com.package.client.Reflection" />
  </generate-with>

Next> Define an interface for our factory class

public interface Reflection {
    public <T, V extends T> T instantiate( Class<V> clazz );
}

Last> Implement 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( );
    }
}

This should generate the factory class ReflectionGenerator in your workspace, check the generated file and tweak the source writer code to generate the code you desire.

Usage GWT.create( Reflection.class ).instantiate( YourClass.class );

I have used a marker interface 'MarkerInterface' in the generator to restrict the number of classes supported by the factory, hence as a result all the participating classes must implement 'MarkerInterface'

这篇关于如何在gwt的类名中创建新的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆