2016-08-17 46 views
1

我有一個自定義轉換器JSON.NET解決嵌套接口列表混凝土類

public class ConcreteTypeConverter<T> : JsonConverter 
    { 
     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      serializer.Serialize(writer, value); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      return serializer.Deserialize<T>(reader); 
     } 

     public override bool CanConvert(Type objectType) 
     { 
      return true; 
     } 
    } 

然後我有下面的類的&接口

[DataContract] 
public class Health : IHealth 
{ 
    [DataMember(Name = "status")] 
    public string Status { get; set; } 
    [DataMember(Name = "alerts")] 
    [JsonConverter(typeof(ConcreteTypeConverter<List<Alert>>))] 
    public IList<IAlert> Alerts { get; set; } 
} 
[DataContract] 
public class Alert : IAlert 
{ 
    [DataMember(Name = "code")] 
    public string Code { get; set; } 
} 
public interface IAlert 
{ 
    string Code { get; set; } 
} 
public interface IHealth 
{ 
    string Status { get; set; } 
    IList<IAlert> Alerts { get; set; } 
} 

我怎樣才能轉換器映射的IList列表?

當前的代碼拋出

Unable to cast object of type 'System.Collections.Generic.List`1[xxx.Services.xxx.New.Alert]' to type 'System.Collections.Generic.IList`1[xxx.Services.xxx.Configuration.Model.New.IAlert]'. 
+0

你已經「X標記出」的命名空間的不同部分異常消息中的Alert類。他們實際上是相同的還是不同的? –

+0

他們是不同的。第一個是具體類,第二個是具體類繼承的接口。這兩個都在兩個獨立的項目中。 –

+0

這就是我所懷疑的。 galenius答案頂部的鏈接解釋了爲什麼我想知道:) –

回答

3

你的問題不是該轉換器,它是.NET類型系統。 List<Alert>不能鑄造到IList<IAlert>,只能到IList<Alert>,這是因爲IList<T>不是協變(see explanation here和其他地方)。

你可以做什麼,正在撰寫您的收藏屬性指定的轉換,這需要收集項目類型之間的轉換關心的:

public class ConcreteCollectionTypeConverter<TCollection, TItem, TBaseItem> : JsonConverter 
    where TCollection : ICollection<TBaseItem>, new() 
    where TItem : TBaseItem 
{ 
    public override void WriteJson(
     JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     serializer.Serialize(writer, value); 
    } 

    public override object ReadJson(
     JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var collection = new TCollection(); 
     var items = serializer.Deserialize<IEnumerable<TItem>>(reader); 

     foreach (var item in items) 
     { 
      collection.Add(item); 
     } 

     return collection; 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return typeof(ICollection<TBaseItem>).IsAssignableFrom(objectType); 
    } 
} 

[DataContract] 
public class Health : IHealth 
{ 
    [DataMember(Name = "status")] 
    public string Status { get; set; } 
    [DataMember(Name = "alerts")] 
    [JsonConverter(
     typeof(ConcreteCollectionTypeConverter<List<IAlert>, Alert, IAlert>))] 
    public IList<IAlert> Alerts { get; set; } 
} 
+0

非常感謝。這個自定義轉換器爲我解決了這個問題 –