1

特定のメソッドの呼び出しに関連する String プロパティがあります。

アイコンプロパティを持つこの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();
    }
}

代わりに、次のような正しいメソッドを選択する文字列を作成したい"icon_" + object.getIcon()+ "()"

いくつかの調査を行った結果、リフレクションを使用する必要があることがわかりましたか?これはどのように達成されますか?

4

2 に答える 2

4

インターフェイス MyClientBundle は、 ClientBundleではなく ClientBundleWithLookup を拡張する必要があります。

ClientBundleWithLookup には、リソース名 (メソッド名) からリソースを取得できる getResource(String name) メソッドがあります。

于 2013-10-29T14:53:29.887 に答える
2

アノテーションのアイコン名で getter メソッドをキャッシュし、そのキャッシュを使用して getter を呼び出します。

以下のコードは、1 レベル上のインターフェイスからのみ注釈を取得します。何らかの理由でさらに高くする必要がある場合は、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");
于 2013-10-28T19:10:59.750 に答える