The present code for readonly collections only works for classes that are or inherit from ReadOnlyCollection<>.
The following changes adds support for any collections that are IEnumerable<> and have an appropate constructor taking an appropiate IEnumerable<>.
Changes add to the end to if-else lists where previously would have just changes so should not affect any other senarios.
In JsonSerializerInternalReader.CreateList() Replace
else if (ReflectionUtils.InheritsGenericDefinition(contract.CreatedType, typeof(ReadOnlyCollection<>)))
{
list = (IList) ReflectionUtils.CreateInstance(contract.CreatedType, list);
}
With
else if (ReflectionUtils.InheritsGenericDefinition(contract.CreatedType, typeof(ReadOnlyCollection<>)))
{
list = (IList) ReflectionUtils.CreateInstance(contract.CreatedType, list);
}
else if (ReflectionUtils.ImplementsGenericDefinition(contract.CreatedType, typeof(IEnumerable<>)))
{
return ReflectionUtils.CreateInstance(contract.CreatedType, list);
}
In CollectionUtils.CreateList() Replace
else
{
list = null;
}
With
else if (ReflectionUtils.ImplementsGenericDefinition(listType, typeof(IEnumerable<>)))
{
Type readOnlyCollectionContentsType = listType.GetGenericArguments()[0];
Type genericEnumerable = ReflectionUtils.MakeGenericType(typeof(IEnumerable<>), readOnlyCollectionContentsType);
bool suitableConstructor = false;
foreach (ConstructorInfo constructor in listType.GetConstructors())
{
IList<ParameterInfo> parameters = constructor.GetParameters();
if (parameters.Count == 1)
{
if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
{
suitableConstructor = true;
break;
}
}
}
if (!suitableConstructor)
throw new Exception("Read-only type {0} does not have a public constructor that takes a type that implements {1}.".FormatWith(CultureInfo.InvariantCulture, listType, genericEnumerable));
// can't add or modify a readonly list
// use List<T> and convert once populated
list = CreateGenericList(readOnlyCollectionContentsType);
isReadOnlyOrFixedSize = true;
}
else
{
list = null;
}