What's an Immutable Class?
The term immutable in OOP is used to be mean that once an object is created, its content cannot be changed; a class is immutable if its instances are immutable.
To create a object which is immutable you need to make sure that the following conditions are met:
- The Class should be final (sealed)
- The Properties of the class should be private and should not have any setter methods
The above mentioned are bare minimum conditions that needs to be satisfied to make the object immutable; to learn more on Immutability in C# you can see:
How To Serialize an Immutable Class
Obviously you can't simply add the Serializable attribute to make an immutable class serializable 'cause its properties are readonly, so you need to implement explicitly the ISerializable interface to control the serialization/deserialization process; to expose the class through a Web Service, you must implement also the IXmlSerializable interface.
Maybe an example will be useful for you:
using System;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
[Serializable]
public sealed class Car : ISerializable, IXmlSerializable
{
public Car() {}
public Car(int id, string model, DateTime creationDate)
{
_id = id;
_model = model;
_creationDate = creationDate;
}
private int _id = -1;
public int Id
{
get { return _id; }
}
private string _model = string.Empty;
public string Model
{
get { return _model; }
}
private DateTime _creationDate = DateTime.MinValue;
public DateTime CreationDate
{
get { return _creationDate; }
}
#region ISerializable Members
private Car(SerializationInfo info, StreamingContext context)
{
_id = info.GetInt32("Id");
_model = info.GetString("Model");
_creationDate = info.GetDateTime("CreationDate");
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Id", _id);
info.AddValue("Model", _model);
info.AddValue("CreationDate", _creationDate);
}
#endregion
#region IXmlSerializable Members
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.LocalName)
{
case "Id":
_id = (reader.IsEmptyElement) ? -1 : reader.ReadElementContentAsInt();
break;
case "Model":
_model = (reader.IsEmptyElement) ? string.Empty : reader.ReadElementContentAsString();
break;
case "CreationDate":
_creationDate = (reader.IsEmptyElement) ? DateTime.MinValue : reader.ReadElementContentAsDateTime();
break;
default:
continue;
}
}
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString("Id", XmlConvert.ToString(_id));
writer.WriteElementString("Model", _model);
writer.WriteElementString("CreationDate", XmlConvert.ToString(_creationDate, XmlDateTimeSerializationMode.Utc));
}
#endregion
}
HTH