2016-08-17 3 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

Вы имеете «х-й изд из» разных частей пространства имен класса '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

большое спасибо. этот пользовательский конвертер исправил эту ту же самую проблему для меня –

Смежные вопросы