Nullable readonly structs are not deserialized with the corresponding constructor call
See original GitHub issueWe’ve successfully used ExtendedXmlSerializer in one of our projects with quite a complicated object graph. During testing, I found another issue that might be a bug. Please consider the following minimal, complete, verifiable example (MCVE):
public sealed class NullableReadonlyStructSerializationTests
{
private readonly IExtendedXmlSerializer _serializer =
new ConfigurationContainer().UseOptimizedNamespaces()
.EnableParameterizedContentWithPropertyAssignments()
.UseAutoFormatting()
.Create();
[Fact]
public void SerializeAndDeserializeInstanceA()
{
var a = new A { Point = new Point(2, 3)} ;
var xml = _serializer.Serialize(a);
var deserializedA = _serializer.Deserialize<A>(xml);
Assert.Equal(a.Point, deserializedA.Point); // This test works fine!
}
[Fact]
public void SerializeAndDeserializeInstanceB()
{
var b = new B { NullablePoint = new Point(24, 7)};
var xml = _serializer.Serialize(b);
var deserializedB = _serializer.Deserialize<B>(xml);
Assert.Equal(b.NullablePoint, deserializedB.NullablePoint);
// This test breaks because the deserialized point is (0,0) instead of (24, 7)
}
}
public sealed class A
{
public Point Point { get; set; }
}
public sealed class B
{
public Point? NullablePoint { get; set; }
}
public readonly struct Point : IEquatable<Point>
{
public Point(int x, int y)
{
X = x;
Y = y;
}
public int X { get; }
public int Y { get; }
public bool Equals(Point other) => X == other.X && Y == other.Y;
public override bool Equals(object? obj) => obj is Point other && Equals(other);
public override int GetHashCode()
{
unchecked
{
return (X * 397) ^ Y;
}
}
public override string ToString() => $"({X}, {Y})";
public static bool operator ==(Point left, Point right) => left.Equals(right);
public static bool operator !=(Point left, Point right) => !left.Equals(right);
}
In the example above, Point
is implemented as an immutable struct. When I use this struct as a regular property in a class (as can be seen in class A
), everything works fine. When I use it as a Point?
, then the corresponding value is deserialized as (0,0) instead of (24, 7). On the IExtendedXmlSerializer
instance, EnableParameterizedContentWithPropertyAssignments
is configured among some other settings (but I don’t think they are the cause of this behavior).
I suspect that when the XML is deserialized as Point?
, the default object initializer of the struct is called instead of the constructor that takes two arguments. Might this be the case? Or did I miss something when configuring the serializer?
Thank you so much for your help in advance!
Issue Analytics
- State:
- Created 3 years ago
- Comments:16 (9 by maintainers)
Top GitHub Comments
Issue-Label Bot is automatically applying the label
bug
to this issue, with a confidence of 0.77. Please mark this comment with 👍 or 👎 to give our bot feedback!Links: app homepage, dashboard and code for this bot.
@Mike-E-angelo I can now confirm that version 3.4.2.1-xufywhoa is fixing this issue.