Serializing object property with custom converter #492
-
|
Hi, [GenerateShape]
public partial class TestModels
{
[MessagePackConverter(typeof(MyConverter))]
public object Tag { get; set; } = null!;
}To serialize the property i created a public class MyConverter : MessagePackConverter<object>
{
public override object? Read(ref MessagePackReader reader, SerializationContext context)
{
if (reader.TryReadNil())
{
return null;
}
//var test = context["test"]; //Dict ist hier leer
var count = reader.ReadArrayHeader(); //Read the array header
// var myClass = context.GetConverter<MyClass>(context.TypeShapeProvider).Read(ref reader, context);
var type = reader.ReadString(); //Read the type name, e.g. "MyClass"
switch (type)
{
case nameof(MyClass):
{
var my = context.GetConverter<MyClass>(context.TypeShapeProvider).Read(ref reader, context);
return my;
break;
}
case nameof(MyClass2):
{
var my = context.GetConverter<MyClass2>(context.TypeShapeProvider).Read(ref reader, context);
return my;
break;
}
default:
throw new NotSupportedException($"Type '{type}' is not supported.");
}
}
public override void Write(ref MessagePackWriter writer, in object? value, SerializationContext context)
{
if (value is null)
{
writer.WriteNil();
return;
}
writer.WriteArrayHeader(2);
switch (value.GetType().Name)
{
case nameof(MyClass):
{
writer.Write(nameof(MyClass));
context.GetConverter<MyClass>(context.TypeShapeProvider).Write(ref writer, (MyClass)value, context);
break;
}
case nameof(MyClass2):
{
writer.Write(nameof(MyClass2));
context.GetConverter<MyClass2>(context.TypeShapeProvider).Write(ref writer, (MyClass2)value, context);
break;
}
default:
throw new NotSupportedException($"Type '{value.GetType().Name}' is not supported.");
}
}
}For testing i create two classes which can set as [GenerateShape]
public partial class MyClass
{
public DateTime t = DateTime.Now;
public DateTimeOffset qt = DateTimeOffset.Now;
}
[GenerateShape]
public class MyClass2
{
public DateTime t = DateTime.Now;
public DateTimeOffset qt = DateTimeOffset.Now;
public string Name2 { get; set; } = "Hallo";
public int Age { get; set; } = 55;
public void AddToDict()
{
Dict.Add(4, "vier");
Dict.Add(5, "fgdfg");
Dict.Add(6, "dfg");
Dict.Add(7, "fgfdg");
}
public Dictionary<int, string> Dict { get; set; } = new Dictionary<int, string>();
}This works great. I can successfully serialize and deserialize objects from type TestModels with the Tag property of type MyClass or MyClass2. Thank you |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 12 replies
-
|
Aside from minor syntax issues that could be improved, what you've done here is quite reasonable. It's actually quite similar to how unions work, but unions require a common base type or interface across all the runtime types. |
Beta Was this translation helpful? Give feedback.
I suggest conforming to what unions supports, because fewer custom converters is usually better. And the built-in ones are far more fully featured and optimized than yours or what I'd expect most other hand-authored converters to support.
If you keep your converter though, here's a suggestion: Your
Readmethod shouldn't discard the result fromReadArrayHeader. You should verify that it is exactly 2 before reading more tokens so that you catch bugs or data corruption sooner.