Ho avuto lo stesso problema, quindi ho creato il mio convertitore che utilizza argomenti di tipi noti.
public class JsonKnownTypeConverter : JsonConverter
{
public IEnumerable<Type> KnownTypes { get; set; }
public JsonKnownTypeConverter(IEnumerable<Type> knownTypes)
{
KnownTypes = knownTypes;
}
protected object Create(Type objectType, JObject jObject)
{
if (jObject["$type"] != null)
{
string typeName = jObject["$type"].ToString();
return Activator.CreateInstance(KnownTypes.First(x =>typeName.Contains("."+x.Name+",")));
}
throw new InvalidOperationException("No supported type");
}
public override bool CanConvert(Type objectType)
{
if (KnownTypes == null)
return false;
return (objectType.IsInterface || objectType.IsAbstract) && KnownTypes.Any(objectType.IsAssignableFrom);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
var target = Create(objectType, jObject);
serializer.Populate(jObject.CreateReader(), target);
return target;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Ho definito due metodi di estensione per deserializzare e serializzare:
public static class AltiJsonSerializer
{
public static T DeserializeJson<T>(this string jsonString, IEnumerable<Type> knownTypes = null)
{
if (string.IsNullOrEmpty(jsonString))
return default(T);
return JsonConvert.DeserializeObject<T>(jsonString,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
Converters = new List<JsonConverter>
(
new JsonConverter[]
{
new JsonKnownTypeConverter(knownTypes)
}
)
}
);
}
public static string SerializeJson(this object objectToSerialize)
{
return JsonConvert.SerializeObject(objectToSerialize, Formatting.Indented,
new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.Auto});
}
}
Puoi definire il tuo modo di confrontare e identificare i tipi nei convertiti, io uso solo il nome della classe.