简体   繁体   English

如何将类名作为 arguments 传递并在 GWT jsni 中调用常见的 static 方法?

[英]How to pass class-name as arguments and invoke common static methods in GWT jsni?

I have lot of enum class and all having one common method.我有很多枚举 class 并且都有一种通用方法。 I want to invoke that common method and return dynamically using GWT jsni method.我想调用该常用方法并使用 GWT jsni 方法动态返回。

Let say I have following enum classes in different packages.假设我在不同的包中有以下枚举类。

package A;

enum WidgetType{

   TEXT_BOX("A"),SVG("B");

   String type;

   WidgetType(String type){
      this.type = type;
   }

   public static WidgetType getDescriptiveValue( String type ){
        for(WidgetType widgetType : WidgetType.values()){
            if(widgetType.type.equalsIgnoreCase(type) ) return widgetType;
        }
        return null;
  }
}
package B;

enum MessageType{

   INFO("I"),WARN("W"),ERROR("E");

   String type;

   MessageType(String type){
      this.type = type;
   }

   public static MessageType getDescriptiveValue( String type ){
        for(MessageType messageType : MessageType.values()){
            if(messageType.type.equalsIgnoreCase(type) ) return messageType;
        }
        return null;
  }
}

Somewhat I will get enum full qualified names in string like [A.WidgetType,B.MessageType].在某种程度上,我会在 [A.WidgetType,B.MessageType] 之类的字符串中获得枚举完整限定名。

Based on this value I want to invoke enum class getDescriptiveValue method using JSNI.基于这个值,我想使用 JSNI 调用枚举 class getDescriptiveValue 方法。

So How to achieve this in GWT jsni.那么如何在 GWT jsni 中实现这一点。

When I try to pass class name as arguments like below I am getting compile time error.当我尝试将 class 名称传递为 arguments 时,如下所示,我收到编译时错误。

Approach 1:方法一:

native void enumValue(String enumClass,String value) /*-{
                console.log($entry(@enumClass::getDescriptiveValue(Ljava/lang/String;)(value)) );
            }-*/;

Approach 2:方法二:

native void enumValue(String enumClass,String value) /*-{
                console.log(@enumClass::getDescriptiveValue(Ljava/lang/String;)(value));
            }-*/;

I don't know is there any way to use Java Reflection in GWT client side?我不知道有没有办法在 GWT 客户端使用 Java 反射?

Please suggest me how to achieve this?请建议我如何实现这一目标?

Put simply, this will not work - the JSNI syntax for java types/members is only a way to write plain code which will be evaluated at compile time into the JS equivalent of the member you are describing.简而言之,这不起作用 - java 类型/成员的 JSNI 语法只是一种编写纯代码的方法,该代码将在编译时评估为您所描述的成员的 JS 等效项。 You cannot simply turn a string into a class literal.您不能简单地将字符串转换为 class 文字。

Instead, depending on how many enums you may wish to support in this way, consider constructing a Map<String, Map<String, Object>> of the enum types and param types you are looking for.相反,根据您可能希望以这种方式支持的枚举数量,考虑构建您正在寻找的枚举类型和参数类型的Map<String, Map<String, Object>> This will require either manual code to list each enum type, or code generation to do this for you, and has the added advantage of not including JSNI.这将需要手动代码来列出每个枚举类型,或者需要代码生成来为您执行此操作,并且具有不包括 JSNI 的额外优势。

Consider a type like this, which requires that each Enum you give it implements some HasType interface, which ensures that all have a getType() method, so they can be reflected on in the same way.考虑一个像这样的类型,它要求你给它的每个 Enum 实现一些 HasType 接口,这确保所有的都有一个 getType() 方法,所以它们可以以相同的方式反映。

public class EnumLookup {
  private final Map<String, Map<String, Object>> enumCache = new HashMap<>();

  /** Helper that you can call internally or externally to build up the cache */
  public <E extends HasType> void register(Class<E> type, E[] values) {
    Map<String, Object> values = enumCache.computeIfAbsent(type.toString(), classname -> new HashMap<>());
    for (E enumValue : values) {
      values.put(enumValue.getType().toLowerCase(), enumValue);
    }
  }
  /** And now the method you are trying to write */
  public <E extends HasType> void enumValue(String enumClass, String value) {
    // use of toLowerCase here and above ensures that type strings will match like
    // in your original java
    return (E) enumCache.get(enumClass).get(value.toLowerCase());
  }
}

and then populate the cache somewhere然后在某处填充缓存

EnumCache cache = new EnumCache();

cache.register(WidgetType.class, WidgetType.values());
cache.register(MessageType.class, MessageType.values());
//...

Another way would be for the map to contain a Function<String, Object> , and use that to point at the getDescriptiveValue via a method reference.另一种方法是让 map 包含一个Function<String, Object> ,并使用它通过方法引用指向getDescriptiveValue Then the registration would look like this:然后注册将如下所示:

cache.register(WidgetType.class, WidgetType::getDescriptiveValue);
cache.register(MessageType.class, MessageType::getDescriptiveValue);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM