1

Closed

Add support for general immutable collections. (with code)

description

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;
}
Closed Mar 7, 2013 at 5:32 AM by JamesNK
Done. I modified your code a bit but the end effect is the same.

comments