Поскольку отражение на стороне клиента невозможно, единственное решение, имитирующее отражение, заключается в использовании отложенного связывания.
Используйте отложенную привязку, чтобы обнаружить все классы, для которых вы хотите создать экземпляр с именем класса во время компиляции. Вы можете использовать интерфейс маркера на всех таких классах, чтобы помочь TypeOracle идентифицировать их. Вы динамически генерируете фабричный класс, который принимает простое имя класса и возвращает вновь созданный объект этого класса. Подход очень прост, и вы найдете хорошее объяснение отложенного связывания в учебниках Google для загрузки.
Edit: -
Некоторый скелетный код, чтобы вы начали. (Урезанная версия моего производственного кода, проверьте на ошибки компилятора в сгенерированном файле! И отладьте поток)
First> Добавьте следующую ошибку в ваш * .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'