Skip to content

Commit 97baf14

Browse files
authored
Fix array of user defined structs serialization failure (#235)
1 parent 6f23f0a commit 97baf14

File tree

2 files changed

+93
-7
lines changed

2 files changed

+93
-7
lines changed

src/Hyperion.Tests/CollectionTests.cs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,5 +616,87 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
616616
return os;
617617
}
618618
}
619-
}
619+
620+
[Fact]
621+
public void CanSerializeNullableIntArray()
622+
{
623+
SerializeAndAssert(new int?[]{1, 2, 3, 4, 5});
624+
}
625+
626+
[Fact]
627+
public void CanSerializeLongArray()
628+
{
629+
SerializeAndAssert(new []{1L, 2L, 3L, 4L, 5L});
630+
}
631+
632+
[Fact]
633+
public void CanSerializeNullableLongArray()
634+
{
635+
SerializeAndAssert(new long?[]{1L, 2L, 3L, 4L, 5L});
636+
}
637+
638+
[Fact]
639+
public void CanSerializeShortArray()
640+
{
641+
SerializeAndAssert(new short[]{1, 2, 3, 4, 5});
642+
}
643+
644+
[Fact]
645+
public void CanSerializeNullableShortArray()
646+
{
647+
SerializeAndAssert(new short?[]{1, 2, 3, 4, 5});
648+
}
649+
650+
[Fact]
651+
public void CanSerializeStringArray()
652+
{
653+
SerializeAndAssert(new []{"1", "2", "3", "4", "5"});
654+
}
655+
656+
[Fact]
657+
public void CanSerializeDateTimeOffsetArray()
658+
{
659+
SerializeAndAssert(new []
660+
{
661+
DateTimeOffset.Now,
662+
DateTimeOffset.UtcNow,
663+
});
664+
}
665+
666+
[Fact]
667+
public void CanSerializeStructArray()
668+
{
669+
SerializeAndAssert(new IStructInterface[]
670+
{
671+
new PrimitiveStruct {Int = 1, Long = 1, String = "1"},
672+
new PrimitiveStruct {Int = 2, Long = 2, String = "2"},
673+
new PrimitiveStruct {Int = 3, Long = 3, String = "3"},
674+
new PrimitiveStruct {Int = 4, Long = 4, String = "4"},
675+
new PrimitiveStruct {Int = 5, Long = 5, String = "5"},
676+
});
677+
}
678+
679+
private interface IStructInterface
680+
{
681+
int Int { get; set; }
682+
long Long { get; set; }
683+
string String { get; set; }
684+
}
685+
686+
private struct PrimitiveStruct : IStructInterface
687+
{
688+
public int Int { get; set; }
689+
public long Long { get; set; }
690+
public string String { get; set; }
691+
}
692+
693+
private void SerializeAndAssert<T>(T[] expected)
694+
{
695+
Serialize(expected);
696+
Reset();
697+
var res = Deserialize<T[]>();
698+
Assert.Equal(expected, res);
699+
AssertMemoryStreamConsumed();
700+
}
701+
}
620702
}

src/Hyperion/SerializerFactories/ArraySerializerFactory.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
#endregion
99

1010
using System;
11+
using System.Collections;
1112
using System.Collections.Concurrent;
1213
using System.IO;
14+
using System.Linq;
1315
using Hyperion.Extensions;
1416
using Hyperion.ValueSerializers;
1517

@@ -21,7 +23,7 @@ internal sealed class ArraySerializerFactory : ValueSerializerFactory
2123

2224
public override bool CanDeserialize(Serializer serializer, Type type) => CanSerialize(serializer, type);
2325

24-
private static void WriteValues<T>(T[] array, Stream stream, Type elementType, ValueSerializer elementSerializer, SerializerSession session)
26+
private static void WriteValues(Array array, Stream stream, Type elementType, ValueSerializer elementSerializer, SerializerSession session)
2527
{
2628
Int32Serializer.WriteValueImpl(stream, array.Length, session);
2729
var preserveObjectReferences = session.Serializer.Options.PreserveObjectReferences;
@@ -30,12 +32,13 @@ private static void WriteValues<T>(T[] array, Stream stream, Type elementType, V
3032
stream.WriteObject(value, elementType, elementSerializer, preserveObjectReferences, session);
3133
}
3234
}
33-
private static void ReadValues<T>(int length, Stream stream, DeserializerSession session, T[] array)
35+
36+
private static void ReadValues(int length, Stream stream, DeserializerSession session, Array array)
3437
{
3538
for (var i = 0; i < length; i++)
3639
{
37-
var value = (T)stream.ReadObject(session);
38-
array[i] = value;
40+
var value = stream.ReadObject(session);
41+
array.SetValue(value, i);
3942
}
4043
}
4144

@@ -57,7 +60,7 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
5760
session.TrackDeserializedObject(array);
5861
}
5962

60-
ReadValues(length, stream, session, (dynamic)array);
63+
ReadValues(length, stream, session, array);
6164

6265
return array;
6366
};
@@ -68,7 +71,8 @@ public override ValueSerializer BuildSerializer(Serializer serializer, Type type
6871
session.TrackSerializedObject(arr);
6972
}
7073

71-
WriteValues((dynamic)arr, stream, elementType, elementSerializer, session);
74+
// This janky way of converting array to Array is done to get around the problem of ValueType arrays
75+
WriteValues(((IEnumerable)arr).Cast<object>().ToArray(), stream, elementType, elementSerializer, session);
7276
};
7377
arraySerializer.Initialize(reader, writer);
7478

0 commit comments

Comments
 (0)