Why is protobuf deserialization not working for OffsetDictionary member variable? It works fine if I don't use Dictionary as backing field. Also, it works fine if the type of OffsetDictionary is changed from complex type to simple SortedDictionary. Am I missing something here?
[ProtoContract]
Public class Test
{
[ProtoMember(1)]
public DateTime BaseDate {get; set;};
[ProtoMember(2)]
public SortedDictionary<short, SortedDictionary<short, uint>> OffsetDictionary
{
get
{
var output = new SortedDictionary<short, SortedDictionary<short, uint>>();
if (this.Dictionary != null)
{
foreach (var item in this.Dictionary)
{
var timeSpan = item.Key - this.BaseDate;
short offset = Convert.ToInt16(timeSpan.TotalDays);
output.Add(offset, item.Value);
}
}
return output;
}
set
{
if (this.Dictionary == null)
{
this.Dictionary = new SortedDictionary<DateTime, SortedDictionary<short, uint>>();
}
foreach (var item in value)
{
this.Dictionary.Add(this.BaseDate.AddDays(item.Key), item.Value);
}
}
}
public SortedDictionary<DateTime, SortedDictionary<short, uint>> Dictionary { get; set; }
}
The problem here is the assumption that the deserializer calls the setter - either at all, or exactly when you expect; it is not required to. The serializer assumes reasonably typical implementations, in which case the following is perfectly reasonable:
Although note that assigning at the start (where
setValueis assigned) would also be legitimate.As it happens, you can sort of make this work by using
but... it works for the wrong reasons IMO, as that could also be implemented with the same pseudo-code as above, but just adding a
.Clear(), which wouldn't change the output.Frankly, I'm not sure that I really like the overall design here; personally, I'd keep the data in the form you're going to serialize, and add utility methods on
Testthat do the flip, i.e.However, you could also do this using a wrapper layer - although it is much more work: