Как создать новый экземпляр из имени класса в gwt

У меня есть интервал класса следующее имя com.test.TestClass

Однажды в моем коде я должен получить экземпляр этого класса, только имея строку имени класса. Я попытался использовать GWT.create() Но это работает только в dev режиме. Может любой говорить мне, как получить экземпляр в gwt от имени класса.

7
задан DonX 14 June 2010 в 03:59
поделиться

1 ответ

Поскольку отражение невозможно на стороне клиента, единственное решение, которое вам нужно имитировать, - это использование отложенного связывания.

Используйте отложенное связывание, чтобы обнаружить все классы, которые вы хотите создать с именем класса во время компиляции. Вы можете использовать интерфейс маркера для всех таких классов, чтобы помочь TypeOracle идентифицировать их. Вы динамически генерируете фабричный класс, который принимает простое имя класса и возвращает вновь созданный объект этого класса. Подход очень прост, и вы найдете хорошее объяснение отложенной привязки в руководствах Google по загрузке.

Изменить: - Скелетный код для начала. (Урезанная версия моего производственного кода, проверьте наличие ошибок компилятора в сгенерированном файле! И отладьте поток)

Сначала> Добавьте следующее рекламное объявление в свой * .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 в вашей рабочей области, проверить сгенерированный файл и настроить исходный код записи, чтобы сгенерируйте желаемый код.

Использование GWT.create (Reflection.class) .instantiate (YourClass.class);

Я использовал интерфейс маркера 'MarkerInterface' в генераторе, чтобы ограничить количество классов поддерживается фабрикой, поэтому в результате все участвующие классы должны реализовать 'MarkerInterface'

14
ответ дан 6 December 2019 в 07:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: