我有一个自定义转换器
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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有以下课程的&接口
[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; }
}
Run Code Online (Sandbox Code Playgroud)
如何获取转换器以将IList映射到List?
当前代码抛出
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]'.
Run Code Online (Sandbox Code Playgroud)
您的问题不是转换器,而是.Net类型的系统。List<Alert>不能强制转换为IList<IAlert>,只能强制转换为IList<Alert>,这是因为IList<T>不协变(请参见此处和其他地方的说明)。
您可以做的是为集合属性编写一个指定的转换器,该转换器负责在集合项类型之间进行转换:
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; }
}
Run Code Online (Sandbox Code Playgroud)