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

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

问题描述

我有一个名为com.test.TestClass

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

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.

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

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.

-一些框架代码让你开始.(我的生产代码的精简版本,检查生成文件中的编译器错误!并调试流程)

- 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> 将以下内容添加到您的 *.gwt.xml 中,以便编译器调用我们的 com.package.ReflectionGenerator,它将生成一个简单的工厂类来模拟客户端上的反射一边.

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 );
}

最后>实现反射生成器

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,检查生成的文件并调整源代码编写器以生成您想要的代码.

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.

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

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

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天全站免登陆