Ora então temos algo como:
void Process(BaseEvent baseEvent);
public class BaseEvent
{
public int Id { get; set; }
public DateTime EventOn { get; set; }
public string User { get; set; }
}
public class LocationEvent : BaseEvent
{
public decimal Latitude { get; set; }
public decimal Longitude { get; set; }
}
public class VehicleEvent : BaseEvent
{
public string LicencePlate { get; set; }
}
O problema surge quando os vários componentes chamam a WebApi, passam os tipos derivados, a WebApi recebe o tipo derivado mas faz sempre deserialize para o tipo base.
Para dar a volta à questão temos de controlar o deserialize através dum JsonConverter e mais uns pózinhos mágicos :)
- Adicionar o pacote nuget do Newtonsoft.Json
Install-Package Newtonsoft.Json
- Alteramos a classe base para ter o tipo que realmente é
public class BaseEvent
{
public string typename { get { return this.GetType().Name; } }
public int Id { get; set; }
public DateTime EventOn { get; set; }
public string User { get; set; }
}
- Criamos um JsonConverter
public class BaseEventJsonCreationConverter : JsonConverter
{
public override bool CanWrite
{
get
{
return false;
}
}
public override bool CanConvert(Type objectType)
{
return typeof(BaseEvent).IsAssignableFrom(objectType);
}
private BaseEvent Create(Type objectType, JObject jObject)
{
var typename = jObject.Value("typename");
if (typeof(LocationEvent).Name.Equals(typename))
{
return new LocationEvent();
}
else if (typeof(VehicleEvent).Name.Equals(typename))
{
return new VehicleEvent();
}
else
{
return new BaseEvent();
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
// Load JObject from stream
JObject jObject = JObject.Load(reader);
// Create target object based on JObject
BaseEvent target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
- Decoramos a classe base com JsonConverter
[JsonConverter(typeof(BaseEventJsonCreationConverter))]
public class BaseEvent
{
. . .
}
E agora a WebApi já faz o deserialize dos objectos correctamente :)
Fonte: Deserialising Json to derived types in Asp.Net Web API
No comments:
Post a Comment