ZeroFormatter
ZeroFormatter copied to clipboard
object with property List<T> does not deserialize where T is a zero formattable object
If you have an object that is [ZeroFormattable] and it has a child List of an object that is also [ZeroFormattable] the deserializer does not work. Looks like zero formatter only handles basic types which is very limiting. Sample classes are below.
[ZeroFormattable]
public class TestObjectZeroFormatter2
{
public TestObjectZeroFormatter2()
{
Children = new List<TestObjectZeroFormatter>();
}
[Index(0)]
public virtual string String { get; set; }
[Index(1)]
public virtual List<TestObjectZeroFormatter> Children { get; set; }
}
[ZeroFormattable]
public class TestObjectZeroFormatter
{
[Index(0)]
public virtual string String { get; set; }
[Index(1)]
public virtual DateTime DateTime { get; set; }
[Index(2)]
public virtual Decimal Decimal { get; set; }
[Index(3)]
public virtual Boolean Boolean { get; set; }
[Index(4)]
public virtual int Integer { get; set; }
[Index(5)]
public virtual double Double { get; set; }
[Index(6)]
public virtual DateTime? DateTimeNullable { get; set; }
[Index(7)]
public virtual Decimal? DecimalNullable { get; set; }
[Index(8)]
public virtual Boolean? BooleanNullable { get; set; }
[Index(9)]
public virtual int? IntegerNullable { get; set; }
[Index(10)]
public virtual double? DoubleNullable { get; set; }
}
just released this issue is the same as #63
@grendo Actually you have another issue here: Virtual member call in a constructor
(since you have classes (ref
type) instead of struct).
ZeroFormatter generates derived class inherited to your original one TestObjectZeroFormatter2
, so when you run Children = new List<TestObjectZeroFormatter>();
you are actually trying to set the property of Children
in derived one since C# always use the last child in the hierarchy when resolve call. Children
in ZeroFormatter's generated class can't be initialized yet since it depends on byte buffers you received to deserialize but not processed yet.
In short: it is not ZeroFormatter's fault and should be fixed on your side. All you need is to resolve Virtual member call in a constructor
(it is bad practice anyway).
E.g. you can move initialization to the property declaration:
public virtual List<TestObjectZeroFormatter> Children { get; set; } = new List<TestObjectZeroFormatter>();
or convert it to a property with a backing field and move initialization there if you stick with older syntax/compiler.
Also, you can just remove initialization code and check for null on the consumer's side.
You can read more about this on StackOverflow or in Matthew Edmondson's Blog