Closed federicomrc closed 8 months ago
It's a bit tricky but it is somewhat possible to achieve this behavior manually, by storing a property for your base class that also persists the class name into TOML (eg an extra field TypeName = "B"). Then in the deserializer you can look up this class and use a bit of reflection find the derived class and call TomletMain.To() on that.
Creating user-defined classes at runtime is a bit of a security risk so make sure to limit what classes can be loaded.
An implementation might look something like this:
class A {
public string TypeName { get { return GetType().Name; } } // you could also manually define a TypeName property in A, B, and C, but this saves a bit of work
}
...
TomletMain.RegisterMapper<A>(
null,
tomlValue =>
{
var typeName = tomlTable.GetString("TypeName");
if (typeName == null) throw new Exception("Error loading A: TypeName not given"); // alternately you could assume the absence of a TypeName indicates it is the base class
var cls = allowableLoadedTypes.FirstOrDefault(cls => cls.Name == typeName);
if (cls == null) throw new Exception($"Error loading A: Not allowed to parse a {typeName}");
return (A) TomletMain.To(cls, tomlValue);
}
);
The only catch is that this method probably won't work if you have instances of AA and not just base classes, since the custom deserializer for A will end up calling TomletMain.To(A), which will call the deserializer again, and so on.
EDIT: it looks like TomlCompositeSerializer.For(A)/TomlCompositeDeserializer.For(A) could be used to avoid that problem by manually getting the ordinary serializer, however these classes are internal so they're not accessible to consumers of the library.
I can definitely post a release with those composite serializer/deserializer methods exposed via some sort of API, for this use case.
It would be really useful to be able to serialize and deserialize derived classes. The actual behaviour is the one listed below:
I think it would be very useful if deserialization returned the correct types (or the subtypes "casted" to the base class), i.e.
EDIT: In the first sentence I meant "deserialize derived classes", not "deserialize base classes"