So let's say I have a:
List<IInterface> list;
that has been serialized with TypeNameHandling.Auto
, so it has "dynamic" type information. I can deserialize it fine as Newtonsoft.Json can recognize the type from the $type
and Json can use the correct constructor. So far so good.
Now say I want to override the creation converter with a mehtod:
CustomCreationConverter<IInterface>
that overrides the creation of the object:
public override IInterface Create(Type objectType)
At this point objectType
will always be IInterface
and not a derived implementation, so I have no way to create the correct object. The meta-information of $type
is now lost.
Is there an elegant way to fix this?
Here would be an attempt that does not work:
public class CustomConverter : CustomCreationConverter<Example.IInterface> {
public override Example.IInterface Create(Type objectType) {
return Example.MakeObject(objectType); // this won't work, objectType will always be IInterface
}
}
public class Example {
public interface IInterface { };
public class A : IInterface { public int content; };
public class B : IInterface { public float data; };
public static IInterface MakeObject(Type t) {
if (t == typeof(IInterface)) {
throw new Exception();
}
return t == typeof(A) ? new A() : new B();
}
public static void Serialize() {
var settings = new JsonSerializerSettings() {
TypeNameHandling = TypeNameHandling.Auto
};
JsonSerializer serializer = JsonSerializer.Create(settings);
// serializer.Converters.Add(new CustomConverter()); // ?? can't have both, either CustomConverter or $type
List<IInterface> list = new() { MakeObject(typeof(A)), MakeObject(typeof(B)) };
using (StreamWriter sw = new("example.json")) {
serializer.Serialize(sw, list);
}
// Now read back example.json into a List<IInterface> using MakeObject
// Using CustomConverter won't work
using (JsonTextReader rd = new JsonTextReader(new StreamReader("example.json"))) {
List<IInterface> list2 = serializer.Deserialize<List<IInterface>>(rd);
}
}
}