Serializing Collections: Overview

Description Article
Summary

A collection type implements the IEnumerable interface.
Types that implement the IDictionary or generic IDictionary<TKey, TValue> interfaces are dictionary collections. All others are list collections.

 

Description

Using Collection Types

During the serialization process, collection equivalence is determined by the data contract definition instead of the collection type:

[DataContract(Name = "PurchaseOrder")]
public class PurchaseOrder1
{
    [DataMember]
    public string customerName;
    [DataMember]
    public Collection<Item> items;
    [DataMember]
    public string[] comments;
}

[DataContract(Name = "PurchaseOrder")]
public class PurchaseOrder2
{
    [DataMember]
    public string customerName;
    [DataMember]
    public List<Item> items;
    [DataMember]
    public BindingList<string> comments;
}

The same XML is produced:

<PurchaseOrder>
    <customerName>...</customerName>
    <items>
        <Item>...</Item>
        <Item>...</Item>
        <Item>...</Item>
        ...
    </items>
    <comments>
        <string>...</string>
        <string>...</string>
        <string>...</string>
        ...
    </comments>
</PurchaseOrder>

Using Collection InterfaceTypes

During the serialization process, if collection interface types are used (e.g. IEnumerable, IDictionary, generic IDictionary<TKey, TValue>, or interfaces derived from these interfaces), interface are considered to have collection data contracts and collection equivalence is also determined by the data contract definition instead of the collection type:

[DataContract(Name="Customer")] public class Customer1
{
    [DataMember] public string customerName;
    [DataMember] public Collection<Address> addresses;
}

[DataContract(Name="Customer")] public class Customer2
{
    [DataMember] public string customerName;
    [DataMember] public ICollection<Address> addresses;
}

During deserialization, when the declared type is an interface, the serialization engine chooses a type that implements the declared interface, and that type is instantiated. The choice of type is built into NET framework.

 

Note

Collection types when used polymorphically in place of other collections or collection interfaces are not required to be added to the known types.

If a collection is used polymorphically in place of non-collection types, it must be added to known types.

[DataContract]
public class Employee
{
    [DataMember] public string name = "John Doe";
    [DataMember] public Payroll payrollRecord;
    [DataMember] public Training trainingRecord;
}

[DataContract]
[KnownType(typeof(int[]))] //required because int[] is used polymorphically
[KnownType(typeof(ArrayList))] //required because ArrayList is used polymorphically
public class Payroll
{
    [DataMember] public object salaryPayments = new int[12];
    //float[] not needed in known types because polymorphic assignment is to another collection type
    [DataMember] public IEnumerable<float> stockAwards = new float[12];
    [DataMember] public object otherPayments = new ArrayList();
}

[DataContract]
[KnownType(typeof(List<object>))]
//required because List<object> is used polymorphically
//does not conflict with ArrayList above because it's a different scope,
//even though it's the same data contract
[KnownType(typeof(InHouseTraining))] //Required if InHouseTraining can be used in the collection
[KnownType(typeof(OutsideTraining))] //Required if OutsideTraining can be used in the collection
public class Training
{
    [DataMember] public object training = new List<object>();
}

[DataContract] public class InHouseTraining {
    //...
}

[DataContract] public class OutsideTraining {
    //...
}

References

[1] Data Contract Known Types