Support IEnumerable on ReadObject
Created by: micdenny
Now it is possible to WriteObject every IEnumerable while you can't ReadObject for instance on List this because under the wood the ReadObject creates an Array of T and then simply set on the instance property.
We could support every IEnumerable that has an implementation with a constructor that accept an array.
repro:
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using Syroot.BinaryData;
using Syroot.BinaryData.Extensions;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
var message = new MessageWithList
{
Numbers = new List<ushort> { 123, 32, 12 }
};
Console.WriteLine(JsonConvert.SerializeObject(message, Formatting.Indented));
Console.WriteLine();
Console.WriteLine();
byte[] bytes;
using (var stream = new MemoryStream())
{
stream.WriteObject(message);
bytes = stream.ToArray();
}
for (int i = 0; i < bytes.Length; i++)
{
Console.WriteLine($"[{i}]={bytes[i]}");
}
Console.WriteLine();
Console.WriteLine();
MessageWithList m;
using (var stream = new MemoryStream(bytes))
{
m = stream.ReadObject<MessageWithList>();
}
Console.WriteLine(JsonConvert.SerializeObject(m, Formatting.Indented));
}
}
[BinaryObject(Explicit = true)]
public class MessageWithList
{
[BinaryMember(Order = 1, Length = 3)]
public List<ushort> Numbers { get; set; }
}
[BinaryObject(Explicit = true)]
public class MessageWithArray
{
[BinaryMember(Order = 1, Length = 3)]
public ushort[] Numbers { get; set; }
}
}
if you run with MessageWithArray
everything's fine, instead if you run with MessageWithList
you get the exception:
Unhandled Exception: System.ArgumentException: Object of type 'System.UInt16[]' cannot be converted to type 'System.Collections.Generic.List`1[System.UInt16]'.
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
at Syroot.BinaryData.Extensions.StreamExtensions.ReadMember(Stream stream, Object instance, Int64 startOffset, ByteConverter converter, MemberData member)
at Syroot.BinaryData.Extensions.StreamExtensions.ReadCustomObject(Stream stream, Type type, Object instance, Int64 startOffset, ByteConverter converter)
at Syroot.BinaryData.Extensions.StreamExtensions.ReadObject(Stream stream, Object instance, BinaryMemberAttribute attribute, Type type, ByteConverter converter)
at Syroot.BinaryData.Extensions.StreamExtensions.ReadObject[T](Stream stream, ByteConverter converter)
at ConsoleApp3.Program.Main(String[] args) in ConsoleApp3\ConsoleApp3\Program.cs:line 42