Skip to content

Commit

Permalink
As reported in Issue #216, when using a calculated binding,
Browse files Browse the repository at this point in the history
with a ValueGetter, the getter appears to be evaluted only once
when initially converted to a TypeNode.
This is unfortunately prior to any deserialized values being realised.

This is a slightly hacky solution, but simply re-attempts to evaluate
getters where this is the case.


Signed-off-by: Bevan Weiss <[email protected]>
  • Loading branch information
bevanweiss committed Jun 3, 2023
1 parent 732c2c4 commit a374d52
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
27 changes: 27 additions & 0 deletions BinarySerializer.Test/Issues/Issue216/Issue216Test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BinarySerialization.Test.Issues.Issue216
{
[TestClass]
public class Issue216Tests : TestBase
{
[TestMethod]
public void TestIssue216()
{
var expected = new Preview
{
ResolutionX = 2,
ResolutionY = 3,
Data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
Empty = 0,
};

var actual = Roundtrip(expected, new byte[] { 2, 0, 0, 0, 3, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 0 });
Assert.AreEqual(expected.ResolutionX, actual.ResolutionX);
Assert.AreEqual(expected.ResolutionY, actual.ResolutionY);
Assert.AreEqual(expected.Data.Length, actual.Data.Length);
for (int i = 0; i < expected.Data.Length; i++)
Assert.AreEqual(expected.Data[i], actual.Data[i]);
}
}
}
27 changes: 27 additions & 0 deletions BinarySerializer.Test/Issues/Issue216/PreviewClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace BinarySerialization.Test.Issues.Issue216
{
public class Preview
{
/// <summary>
/// Gets the image width, in pixels.
/// </summary>
[FieldOrder(0)]
public uint ResolutionX { get; set; }

/// <summary>
/// Gets the image height, in pixels.
/// </summary>
[FieldOrder(2)]
public uint ResolutionY { get; set; }

[Ignore]
public uint DataSize => ResolutionX * ResolutionY * 2;

[FieldOrder(3)]
[FieldCount(nameof(DataSize), BindingMode = BindingMode.OneWay)]
public byte[] Data { get; set; }

[FieldOrder(4)]
public uint Empty;
}
}
6 changes: 6 additions & 0 deletions BinarySerializer/Graph/Binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ public object GetValue(ValueNode target)

CheckSource(source);

// When using a calculated Ignore field, the evaluation of the value is not
// deferred until required non-Ignore fields are calculated.
// This is a hack, but if the value is null, we will re-evaluate the getter
if (source.Value == null && source.TypeNode.ValueGetter != null)
source.Value = source.TypeNode.ValueGetter.Invoke(source.Parent.Value);

return ValueConverter == null
? source.Value
: Convert(source.Value, target.CreateLazySerializationContext());
Expand Down

0 comments on commit a374d52

Please sign in to comment.