2013-10-28 30 views
1

我有一個String屬性,涉及到調用一個特定的方法。如何使用字符串調用GWT ClientBundle接口的方法?

我有這樣的DTO,與圖標屬性

public class MyDto 
{ 
    String icon; // "first", "second", "third" etc 

    public String getIcon() 
    { 
     return icon; 
    } 
} 

在我的界面我有以下方法:(GWT ClientBundle)

public interface MyClientBundle extends ClientBundle 
{ 
    @Source("icon_first.jpg") 
    ImageResource icon_first(); 

    @Source("logo_second.jpg") 
    ImageResource icon_second(); 

    @Source("icon_third.jpg") 
    ImageResource icon_third(); 
} 

我目前使用與選擇語句的查詢效率低,但想通過建立一個字符串來選擇正確的方法:

public ImageResource getValue(MyDto object) 
{ 
    return getIconFromCode(object.getIcon()); 
} 

private ImageResource getIconFromCode(String code) 
{ 
    if(code.equalsIgnoreCase("first")) 
    { 
     return resources.icon_first(); 
    } 
    else if(code.equalsIgnoreCase("second")) 
    { 
     return resources.icon_second(); 
    } 
    else if(code.equalsIgnoreCase("third")) 
    { 
     return resources.icon_third(); 
    } 
    else 
    { 
     return resources.icon_default(); 
    } 
} 

I wan噸建立一個字符串來選擇正確的方法,而不是像"icon_" + object.getIcon()+ "()"

做了一些研究,我明白我需要使用反射?這將如何完成?

+0

你在用什麼?反思有點複雜,可能不是你想要的,我猜測。您可以使用數組,ArrayList或HashMap來快速訪問。一個數組和ArrayList會讓你通過int索引查找,而HashMap會讓你通過任何鍵索引,包括一個int索引。然後,在MyClientBundle中,您可以創建一個getter方法,該方法接受一個鍵/索引參數並返回關聯的ImageResource。 – stoooops

+0

ClientBundle是一個GWT接口,它創建一個具體的類,其中每個方法映射到特定的圖像。我想每次渲染正確的圖像,但我不想要一個具有20個左右元素的開關(或者說是 - else)。 – slugmandrew

+0

我不認爲我可以添加一個方法到MyClientBundle,因爲它是一個接口,實際的類是由代碼生成器創建的。無論如何,由於GWT模擬器不支持反射,我仍然是個笨拙的人。任何建議歡迎:) – slugmandrew

回答

4

接口MyClientBundle應該延伸ClientBundleWithLookup代替ClientBundle。

ClientBundleWithLookup有一個getResource(String name)方法,可以讓您從資源名稱(方法名稱)中檢索資源。

2

通過註釋中的圖標名稱緩存getter方法,並使用該緩存來調用getter。

下面的代碼只能從接口的上一級獲得註釋。如果由於某種原因需要更高版本,只需遞歸調用cacheGettersFor()方法即可。

在這裏沒有檢查以確保圖標getter方法具有正確的簽名(不帶參數,返回ImageResource),如果您使用任何此代碼,則需要添加。

public class IconGetterCache { 
    class IconGetterCacheForBundleType { 
     private Map<String, Method> _iconGetters = new HashMap<>(); 
     private Class<?> _runtimeClass; 

     private void cacheGettersFor(Class<?> forClazz) { 
      for (Method method : forClazz.getMethods()) { 
       Source iconSourceAnnotation = method.getAnnotation(Source.class); 
       if (iconSourceAnnotation != null) { 
        _iconGetters.put(iconSourceAnnotation.value(), method); 
       } 
      } 
     } 

     IconGetterCacheForBundleType(final Class<?> runtimeClass) { 
      _runtimeClass = runtimeClass; 
      for (Class<?> iface : _runtimeClass.getInterfaces()) { 
       cacheGettersFor(iface); 
      } 
      cacheGettersFor(_runtimeClass); 
     } 

     public ImageResource getIconFromBundle(ClientBundle bundle, String iconName) { 

      if (!_runtimeClass.isAssignableFrom(bundle.getClass())) { 
       throw new IllegalArgumentException("Mismatched bundle type"); 
      } 

      Method getter = _iconGetters.get(iconName); 
      if (getter == null) { return null; } 
      try { 
       return (ImageResource) getter.invoke(bundle); 
      } 
      catch (Throwable t) { 
       throw new RuntimeException("Could not get icon", t); 
      } 
     } 
    } 

    private Map<Class<?>, IconGetterCacheForBundleType> _getterCaches = new HashMap<>(); 

    //main entry point, use this to get your icons 
    public ImageResource getIconFromBundle(ClientBundle bundle, String iconName) { 
     final Class<? extends ClientBundle> getterClass = bundle.getClass(); 
     IconGetterCacheForBundleType getterCache = _getterCaches.get(getterClass); 
     if (getterCache == null) { 
      _getterCaches.put(getterClass, getterCache = new IconGetterCacheForBundleType(getterClass)); 
     } 
     return getterCache.getIconFromBundle(bundle, iconName); 
    } 
} 


//Here's how I tested 
IconGetterCache gc = new IconGetterCache(); 
MyClientBundle concreteClientBundle = new MyClientBundle() { 
    @Override 
    public ImageResource icon_first() { 
     //return correct icon 
    } 

    @Override 
    public ImageResource icon_second() { 
     //return correct icon 
    } 

    @Override 
    public ImageResource icon_third() { 
     //return correct icon 
    } 
}; 
gc.getIconFromBundle(concreteClientBundle, "icon_first.jpg"); 
+0

反射在GWT中起作用嗎? – Fedy2

+0

@ Fedy2 - 不,你不能在GWT中使用反射 – otonglet

+0

這個解決方案是否使用反射? – Fedy2