Hyperion
Hyperion copied to clipboard
Hyperion failed with "Index was out of range" in `GetDeserializedObject` when payload has Duplicate Values
My payload contains data like this in an FSharp Record. The error goes away if the values if the values are different. Only occurs when preserve object refs
is true.
Section = Some "sd"
SubDivision = Some "sd"
This is the exception.
$exception {"Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: index"} System.ArgumentOutOfRangeException
Here is the line that fails.
public class DeserializerSession
{
////
public object GetDeserializedObject(int id)
{
return _objectById[id]; // <- here
}
////
Stack Trace
> Hyperion.dll!Hyperion.DeserializerSession.GetDeserializedObject(int id = 14) Line 66 C#
Hyperion.dll!Hyperion.ValueSerializers.ObjectReferenceSerializer.ReadValue(System.IO.Stream stream = {System.IO.MemoryStream}, Hyperion.DeserializerSession session = {Hyperion.DeserializerSession}) Line 34 C#
Hyperion.dll!Hyperion.Extensions.StreamEx.ReadObject(System.IO.Stream stream = {System.IO.MemoryStream}, Hyperion.DeserializerSession session = {Hyperion.DeserializerSession}) Line 172 C#
Here's a failing test in F#, it looks like the root cause is the inclusion of the F# Map type in the Header
type of the Payload
record.
type Header = {
Properties: Map<int,int>;
}
type Payload<'t> =
{
Header: Header;
Value: 't
}
override this.ToString() =
"Envelope: " + this.Value.ToString()
type InnerType = {
OneField : string option
TwoField : string option
}
type OuterType = {
Something : InnerType
FirstField : string option
SecondField : string option
ThirdField : string option
}
let inner = {
OneField = Some "value"
TwoField = Some "value"
}
let toSerialise = {
Header = { Properties = Map.empty; }
Value = inner
}
toSerialise |> Dump |> ignore
let options = Hyperion.SerializerOptions(preserveObjectReferences = true)
let serialiser = Hyperion.Serializer(options)
let ``run test`` =
use inbound = new MemoryStream()
serialiser.Serialize(toSerialise, inbound)
inbound.Flush()
use outbound = new MemoryStream(inbound.ToArray())
let result = serialiser.Deserialize outbound
result
``run test`` |> Dump |> ignore
Ran in LinqPad, using the latest Hyperion from nuget