Code Listings
Serialization
Basic use of DataContractSerializer:
namespace SerialTest
{
[DataContract] public class Person
{
[DataMember] public string Name;
[DataMember] public int Age;
}
}
Person p = new Person { Name = "Stacey", Age = 30 };
DataContractSerializer ds = new DataContractSerializer (typeof (Person));
using (Stream s = File.Create ("person.xml"))
ds.WriteObject (s, p); // Serialize
Person p2;
using (Stream s = File.OpenRead ("person.xml"))
p2 = (Person) ds.ReadObject (s); // Deserialize
Console.WriteLine (p2.Name + " " + p2.Age); // Stacey 30
Formatting the output:
Person p = new Person { Name = "Stacey", Age = 30 };
DataContractSerializer ds = new DataContractSerializer (typeof (Person));
XmlWriterSettings settings = new XmlWriterSettings() { Indent = true };
using (XmlWriter w = XmlWriter.Create ("person.xml", settings))
ds.WriteObject (w, p);
System.Diagnostics.Process.Start ("person.xml");
Overriding data member names:
[DataContract (Name="Candidate", Namespace="http://oreilly.com/nutshell")]
public class Person
{
[DataMember (Name="FirstName")] public string Name;
[DataMember (Name="ClaimedAge")] public int Age;
}
Specifying a binary formatter with the data contract serializer:
Person p = new Person { Name = "Stacey", Age = 30 };
DataContractSerializer ds = new DataContractSerializer (typeof (Person));
MemoryStream s = new MemoryStream();
using (XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (s))
ds.WriteObject (w, p);
MemoryStream s2 = new MemoryStream (s.ToArray());
Person p2;
using (XmlDictionaryReader r = XmlDictionaryReader.CreateBinaryReader (s2,
XmlDictionaryReaderQuotas.Max))
p2 = (Person) ds.ReadObject (r);
Serializing subclasses:
[DataContract, KnownType (typeof (Student)), KnownType (typeof (Teacher))]
public class Person
{
[DataMember] public string Name;
[DataMember] public int Age;
}
[DataContract] public class Student : Person { }
[DataContract] public class Teacher : Person { }
static Person DeepClone (Person p)
{
DataContractSerializer ds = new DataContractSerializer (typeof (Person));
MemoryStream stream = new MemoryStream();
ds.WriteObject (stream, p);
stream.Position = 0;
return (Person) ds.ReadObject (stream);
}
Person person = new Person { Name = "Stacey", Age = 30 };
Student student = new Student { Name = "Stacey", Age = 30 };
Teacher teacher = new Teacher { Name = "Stacey", Age = 30 };
Person p2 = DeepClone (person);
Student s2 = (Student) DeepClone (student);
Teacher t2 = (Teacher) DeepClone (teacher);
Alternative to KnownType on [DataContract]:
DataContractSerializer ds = new DataContractSerializer (typeof (Person),
new Type[] { typeof (Student), typeof (Teacher) } );
Object references:
[DataContract] public class Person
{
[DataMember] public string Name;
[DataMember] public int Age;
[DataMember] public Address HomeAddress;
}
[DataContract, KnownType (typeof (USAddress))]
public class Address
{
[DataMember] public string Street, Postcode;
}
Version tolerance:
[DataContract] public class Person : IExtensibleDataObject
{
[DataMember] public string Name;
[DataMember] public int Age;
ExtensionDataObject IExtensibleDataObject.ExtensionData { get; set; }
}
Member ordering:
[DataContract] public class Person
{
[DataMember (Order=0)] public string Name;
[DataMember (Order=1)] public int Age;
}
Null and empty values:
[DataContract] public class Person
{
[DataMember (EmitDefaultValue=false)] public string Name;
[DataMember (EmitDefaultValue=false)] public int Age;
}
Data contracts and collections:
[DataContract] public class Person
{
[DataMember (Name="Addresses")]
List<Address> _addresses;
public IList<Address> Addresses { get { return _addresses; } }
}
[DataContract] public class Address
{
[DataMember] public string Street, Postcode;
}
Subclassing collection elements:
[DataContract, KnownType (typeof (USAddress))]
public class Address
{
[DataMember] public string Street, Postcode;
}
public class USAddress : Address { }
Customizing collection and element names:
[CollectionDataContract (ItemName="Residence")]
public class AddressList : Collection<Address> { }
[DataContract] public class Person
{
...
[DataMember] public AddressList Addresses;
}
[CollectionDataContract (ItemName="Entry",
KeyName="Kind",
ValueName="Number")]
public class PhoneNumberList : Dictionary <string, string> { }
[DataContract] public class Person
{
...
[DataMember] public PhoneNumberList PhoneNumbers;
}
Serialization and deserialization hooks:
public DateTime DateOfBirth;
[DataMember] public bool Confidential;
[DataMember (Name="DateOfBirth", EmitDefaultValue=false)]
DateTime? _tempDateOfBirth;
[OnSerializing]
void PrepareForSerialization (StreamingContext sc)
{
if (Confidential)
_tempDateOfBirth = DateOfBirth;
else
_tempDateOfBirth = null;
}
Getting started with the binary engine:
[Serializable] public sealed class Person
{
public string Name;
public int Age;
}
Person p = new Person() { Name = "George", Age = 25 };
IFormatter formatter = new BinaryFormatter();
using (FileStream s = File.Create ("serialized.bin"))
formatter.Serialize (s, p);
using (FileStream s = File.OpenRead ("serialized.bin"))
{
Person p2 = (Person) formatter.Deserialize (s);
Console.WriteLine (p2.Name + " " + p.Age); // George 25
}
[NonSerialized]:
[Serializable] public sealed class Person
{
public string Name;
public DateTime DateOfBirth;
// Age can be calculated, so there's no need to serialize it.
[NonSerialized] public int Age;
}
[OnDeserializing] and [OnDeserialized]
public sealed class Person
{
public string Name;
public DateTime DateOfBirth;
[NonSerialized] public int Age;
[NonSerialized] public bool Valid = true;
public Person() { Valid = true; }
}
[OnSerializing] and [OnSerialized]
[Serializable] public sealed class Team
{
public string Name;
Person[] _playersToSerialize;
[NonSerialized] public List<Person> Players = new List<Person>();
[OnSerializing]
void OnSerializing (StreamingContext context)
{
_playersToSerialize = Players.ToArray();
}
[OnSerialized]
void OnSerialized (StreamingContext context)
{
_playersToSerialize = null; // Allow it to be freed from memory
}
[OnDeserialized]
void OnDeserialized (StreamingContext context)
{
Players = new List<Person> (_playersToSerialize);
}
}
[OptionalField] and versioning:
[Serializable] public sealed class Person // Version 2 Robust
{
public string Name;
[OptionalField (VersionAdded = 2)] public DateTime DateOfBirth;
}
ISerializable:
[Serializable] public class Team : ISerializable
{
public string Name;
public List<Person> Players;
public virtual void GetObjectData (SerializationInfo si,
StreamingContext sc)
{
si.AddValue ("Name", Name);
si.AddValue ("PlayerData", Players.ToArray());
}
public Team() {}
protected Team (SerializationInfo si, StreamingContext sc)
{
Name = si.GetString ("Name");
// Deserialize Players to an array to match our serialization:
Person[] a = (Person[]) si.GetValue ("PlayerData", typeof (Person[]));
// Construct a new List using this array:
Players = new List<Person> (a);
}
}
Getting started with XmlSerializer:
public class Person
{
public string Name;
public int Age;
}
p.Name = "Stacey"; p.Age = 30;
XmlSerializer xs = new XmlSerializer (typeof (Person));
using (Stream s = File.Create ("person.xml"))
xs.Serialize (s, p);
Person p2;
using (Stream s = File.OpenRead ("person.xml"))
p2 = (Person) xs.Deserialize (s);
Console.WriteLine (p2.Name + " " + p2.Age); // Stacey 30
Attributes, names and namespaces:
public class Person
{
[XmlElement ("FirstName")] public string Name;
[XmlAttribute ("RoughAge")] public int Age;
}
XML element order:
public class Person
{
[XmlElement (Order = 2)] public string Name;
[XmlElement (Order = 1)] public int Age;
}
XmlSerializer and subclassing:
[XmlInclude (typeof (Student))]
[XmlInclude (typeof (Teacher))]
public class Person { public string Name; }
public class Student : Person { }
public class Teacher : Person { }
public void SerializePerson (Person p, string path)
{
XmlSerializer xs = new XmlSerializer (typeof (Person));
using (Stream s = File.Create (path))
xs.Serialize (s, p);
}
Alternative:
XmlSerializer xs = new XmlSerializer (typeof (Person),
new Type[] { typeof (Student), typeof (Teacher) } );
Serializing child objects:
public class Person
{
public string Name;
public Address HomeAddress = new Address();
}
public class Address { public string Street, PostCode; }
Person p = new Person(); p.Name = "Stacey";
p.HomeAddress.Street = "Odo St";
p.HomeAddress.PostCode = "6020";
Subclassed child objects, solution 1:
[XmlInclude (typeof (AUAddress))]
[XmlInclude (typeof (USAddress))]
public class Address { public string Street, PostCode; }
public class USAddress : Address { }
public class AUAddress : Address { }
public class Person
{
public string Name;
public Address HomeAddress = new USAddress();
}
Subclassed child objects, solution 2:
public class Address { public string Street, PostCode; }
public class USAddress : Address { }
public class AUAddress : Address { }
public class Person
{
public string Name;
[XmlElement ("Address", typeof (Address))]
[XmlElement ("AUAddress", typeof (AUAddress))]
[XmlElement ("USAddress", typeof (USAddress))]
public Address HomeAddress = new USAddress();
}
Serializing collections with the outer element:
public class Person
{
public string Name;
[XmlArray ("PreviousAddresses")]
[XmlArrayItem ("Location")]
public List<Address> Addresses = new List<Address>();
}
Serializing collections without the outer element:
public class Person
{
public string Name;
[XmlElement ("Address")]
public List<Address> Addresses = new List<Address>();
}
Subclassing collection elements with the outer element:
[XmlArrayItem ("Address", typeof (Address))]
[XmlArrayItem ("AUAddress", typeof (AUAddress))]
[XmlArrayItem ("USAddress", typeof (USAddress))]
public List<Address> Addresses = new List<Address>();
Subclassing collection elements without the outer element:
[XmlElement ("Address", typeof (Address))]
[XmlElement ("AUAddress", typeof (AUAddress))]
[XmlElement ("USAddress", typeof (USAddress))]
public List<Address> Addresses = new List<Address>();
IXmlSerializable:
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
public class Address : IXmlSerializable
{
public string Street, PostCode;
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement();
Street = reader.ReadElementContentAsString ("Street", "");
PostCode = reader.ReadElementContentAsString ("PostCode", "");
reader.ReadEndElement();
}
public void WriteXml (XmlWriter writer)
{
writer.WriteElementString ("Street", Street);
writer.WriteElementString ("PostCode", PostCode);
}
}