2013-04-17 101 views
2

我想提供泛型實例,但不明確聲明模塊實現中的通用參數。Guice無限通用綁定

比方說,我有一個非常優化的Map實現,並希望每個人都使用它。

class MyVeryOptimizedHashMap<K, V> implements Map<K, V> {} 

我知道,以下用法是不是最好的設計模式,但對於例如起見,這是一個有效的要求:

class SomeInjectee { 
    @Inject 
    private Map<String, Integer> myMap; 
} 

要綁定這種情況下,以我所選擇的供應商下模塊聲明的工作原理:

class GenericMapModule extends AbstractModule { 
    protected void configure() { 
    bind(new TypeLiteral<Map<String, Integer>>() {}).toProvider(new TypeLiteral<Provider<MyVeryOptimizedHashMap<String, Integer>>>() {}); 
    } 
} 

問題是,我必須明確指出泛型類型參數,我不可能爲所有可能的類型做:

class SomeOtherInjectee{ 
    @Inject 
    private Map<SomeUnknownKey, Long> myMap; 
} 

這解決了我的問題,但不是很優雅:

class GenericModule extends AbstractModule { 
    protected void configure() { 
    bind(new TypeLiteral<Map<?, ?>>() {}).toProvider(new Provider<Map<?,?>>() { 
     public Map<?, ?> get() { 
     return new MyVeryOptimizedHashMap(); 
     } 
    }); 
    } 
} 

class SomeOtherInjectee { 
    private Map<SomeUnknownKey, Long> myMap; 

    @Inject 
    void setMap(Map<?, ?> mapInstance) { 
    myMap = (Map<SomeUnknownKey, Long>) mapInstance; 
    } 
} 

我所尋找的是類似的東西:

class GenericModule extends AbstractModule { 
    protected void configure() { 
    bind(TypeLiteral.anyGenericVariant(Map.class)).toProvider(new TypeLiteral<Provider<MyVeryOptimizedHashMap>>(){});   
    } 
} 

回答

0

如果適合你的情況我會嘗試靜態效用法。

class SomeOtherInjectee { 
    private Map<SomeUnknownKey, Long> myMap = newOptimizedMap(); 

如果你看到吉斯是在仿製藥方面是非常精確的,這是不適用的,然後即,每個通用變種代表一種獨特的結合。所以anyGenericVariant實際上必須列出所有可能的變體,並提前進行綁定。瘋。

在這種情況下,您可以做的是使用TypeListener註冊自定義注入。它看起來像

class SomeOtherInjectee { 
    @InjectOptimizedMap private Map<SomeUnknownKey, Long> myMap; 

或任何您所做的自定義注射註釋。

請參閱here for the full example and explanation關於如何進行自定義注射。

+1

正如我所提到的,這是一個例子,我的實際使用案例與此不同。所以我需要解決這個問題,在我的模塊定義(可能使用Key或TypeLiteral類的一些私有構造函數)內部並按原樣留下注入者。 Guice實際上很懶惰,如果只有Key <-> TypeLiteral匹配可能會被黑客入侵。 – b10y

+0

使用TypeListener方式有什麼問題?你需要c'tor注射嗎? –