2014-01-22 22 views
0

我使用RoboGuice和GSON在我的應用程序如何獲得roboguice的綁定

在某個時候,我需要GSON注入一個JSON到一個接口,但是,GSON犯規知道如何注入接口,除非你提供一個實例創建者,它在實現類和它的接口之間映射的方式與roboguice相同,它也需要這個完全相同的映射。

爲了測試我的應用程序,我想給roboguice和GSON同一實現映射

我如何得到roboguice是我的接口綁定實現的保持,以便將它們傳遞給GsonBuilder InstanceCreator?

回答

0

Roboguice(好的,Guice)能夠「注入界面」,這就是它設計的目的。 假設你有下面的代碼:

public class ExampleClass { 
    @Inject InterfaceType mExampleField; 
    ... 

吉斯會影響它的混凝土亞型您在注射結構中勢必InterfaceTypeInterfaceType當你注入一個ExampleClass實例。比方說,你模塊與外表初始化注射器是這樣的:

public class ExampleModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     bind(InterfaceType.class).to(ConcreteType.class); 
    } 
} 

提供了以下定義:如果現在注入的ExampleClass某處

public interface InterfaceType { } 

public class ConcreteType implements InterfaceType { ... } 

,例如

@Inject ExampleClass mExample; 

然後mExample.mExampleField將引用ConcreteType對象。

現在,我的理解是,你想要做的是建立一個Guice模塊綁定到InterfaceType的具體類的實體。你可以做這樣的事情:

public class ExampleClass { 
    @Inject InterfaceType mDummyExampleField; 

    private final Gson mGson = ...; 

    ... 

    public InterfaceType buildBoundSubTypeFromJson(final String json) { 
     return mGson.fromJson(json, mDummyExampleField.getClass()); 
    } 
} 

和吉斯將動態查找具體類型由mExampleField引用創建此類型的對象實例的。 mExampleField由注入器填充,因此它將成爲您綁定到的InterfaceType接口的具體類型。

這意味着在上述示例中,buildBoundSubTypeFromJson()將返回實際類型ConcreteType的對象。

或者稍微乾淨:

public class Deserializer { 
    private final Class<? extends InterfaceType> mConcreteType; 

    @Inject 
    public Deserializer(final InterfaceType dummy) { 
     mConcreteType = dummy.getClass(); 
    } 

    private final Gson mGson = ...; 

    ... 

    public InterfaceType buildBoundSubTypeFromJson(final String json) { 
     return mGson.fromJson(json, mConcreteType); 
    } 
} 

這樣的作品,但我認爲這將是非常危險的,因爲JSON字符串必須符合您綁定你的界面根據您的電流注入的實際類型設置或接口的所有子類型必須匹配通用的json格式,這兩種格式都不能靜態強制執行。

另一個稍微強一點的解決方案是將您的Json數據反序列化爲一個唯一的實體類型(假設Json數據總是相同的情況),然後通過可以注入的轉換器對象將其轉換爲InterfaceType(並且綁定到與其類型InterfaceType相匹配的子類型的一個綁定)。

還要注意的是,你可以動態地從吉斯通過訪問其配置這樣的檢索類型:

injector 
    .getBinding(InterfaceType.class) 
    .acceptTargetVisitor(new DefaultBindingTargetVisitor<InterfaceType, InterfaceType>() { 
     @Override 
     public InterfaceType visit(LinkedKeyBinding<? extends InterfaceType> binding) { 
      mConcreteType = binding.getLinkedKey().getTypeLiteral()); 
      return visitOther(binding); 
     } 

     // don't forget to override other visit methods if you except other types of bindings ! 
    }); 

,如果你想讓它少了幾分哈克。


所以它看起來像你想在已宣佈的接口類型的字段,如在類型反序列化:

ExampleClass example = mGson.fromJson(json, ExampleClass.class); 

example.mExampleField這裏是空的。這很正常,因爲Gson無法知道你想要實例化哪個對象爲mExampleField

此問題的解決方案是使用custom deserialization,這意味着您要控制該類型的Gson的反序列化過程。

聯絡,以獲得從注射設置具體類型的第一個問題相結合,這應該看起來有點像:

class ExampleDeserializer implements JsonDeserializer<InterfaceType>() { 
    private final Class<? extends InterfaceType> mConcreteType; 

    @Inject 
    public ExampleDeserializer(final InterfaceType dummy) { 
     mConcreteType = dummy.getClass(); 
    } 

    @Override 
    public InterfaceType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     return context.deserialize(json, mConcreteType); 
    } 

}

,不要忘記,你創建註冊這個自定義您的解串器Gson實例:

public class AnotherClass { 
    private final Gson mGson; 

    @Inject 
    public AnotherClass(ExampleDeserializer mExampleDeserializer) { 
     mGson = new GsonBuilder().registerTypeAdapter(InterfaceType.class, mExampleDeserializer).create(); 
     // now you can deserialize ExampleClass Json representation using mGson 
    } 
} 
+0

我的問題是,當我嘗試反序列化一個json字符串,該字符串包含一個寫入pojo中的對象作爲接口,它將它留作空,這是否能解決問題? –

+0

這是另一個問題,我更新了我的答案,以及如何在您的用例中解決它。還添加了關於您可以使用Guice綁定訪問者的事實的說明。 – desseim

相關問題