Search code examples
c#.netdeserializationdatacontractserializercustom-collection

After Deserialization using DataContractSerializer, Collection gets read-only


This should be pretty straight forward but after deserializing my business objects using DataContractSerializer all the custom collections inside them turned to read-only.

To be exact i am trying to manipulate the collection after deserialization by swapping the items inside collection but this is throwing exception saying Collection is read-only. However, before serialization, everything is fine.

An unhandled exception of type 'System.NotSupportedException' occurred in mscorlib.dll Additional information: Collection is read-only.

This is how i have decorated my custom collection class.

[Serializable]
[DataContract]
[KnownType(typeof(RuleBase))]
[KnownType(typeof(RuleSet))]
public class GenericRuleCollection : ObservableCollection<IRule>
{
    //...
}

This is the way i have decorated my business object class.

[Serializable]
[DataContract]
public class RuleSet : GenericRuleContainer
{
    //...
}

[Serializable]
[DataContract(IsReference = true)]
public abstract class GenericRuleContainer : GenericRule, IRuleContainer
{        
    private GenericRuleCollection _children;     
    [DataMember]
    public GenericRuleCollection Children
    {
        get { return _children; }
        set { SetProperty(ref _children, value); }
    }
    //...
}

Serialization and Deserialization piece of code:

public class DataContractSerializer<T>
{
    public void SerializeToFile(string fileName, T obj)
    {
        var serializer = new DataContractSerializer(typeof(T));
        using (FileStream fs = File.Open(fileName, FileMode.Create))
        {                
            serializer.WriteObject(fs, obj);
        }
    }

    public T DeserializeFromFile(string fileName)
    {
        var serializer = new DataContractSerializer(typeof(T));
        using (FileStream fs = File.Open(fileName, FileMode.Open))
        {
            object s2 = serializer.ReadObject(fs);
            return (T)s2;
        }
    }
}

Solution

  • Well after some random research on google i could able to fix this issue by changing attribute decoration from [DataContract] to [CollectionDataContract] on my custom collection class.

    [Serializable]
    [CollectionDataContract]
    [KnownType(typeof(RuleBase))]
    [KnownType(typeof(RuleSet))]
    public class GenericRuleCollection : ObservableCollection<IRule>
    {
        //...
    }