Desterilizing is the process of converting Serialized byte stream into a object.
There are 2 type of Serialization object
1. Binary Formatter -: this will located on System.Runtime.Serialization.Formatters.Binary Namespase. This is most efficient way to do that. But it can read only in the .net framework
2. SoapFormatter -: this located on System.Runtime.Serialization.Formatters.Soap names pace. This is xml based formatter and most reliable way to serializable object that transmit across net work. This can be read non .net framework. This is successfully traversal across firewall than binary formatter. This is not support version compatibility of .net framework.
Object Serialization Step:
- Create a stream object to hold serialized output.
- Create a binary formatter object (its locate in System.Runtime.Serialaization.Formatter.Binary )
- Call the BinaryFormatter or SoapFormatter .Serialize Method to Serialized object and output result to the stream.
C# code
FileStream fs = new FileStream("SerializedData.Dat", FileMode.Create);
BinaryFormatter bf = new BinaryFormatter(); // binary formatter
//SoapFormatter bf = new SoapFormatter(); // for soap Formatter
bf.Serialize(fs, System.DateTime.Now);
fs.Close();
Object are DeSerialization Step:
- Create a stream object to read the serialized output
- Create a Binary Formatter object.
- Create a new object to store the Deserialized data .
- Call the BinaryFormatter.Deserialize method to deserialize the object, and cast it to the correct type.
Ex -:
FileStream fsRead = new FileStream("SerializedData.Dat", FileMode.Open);
BinaryFormatter bfR = new BinaryFormatter();
//SoapFormatter bf = new SoapFormatter(); // for soap Formatter
DateTime data;
data =(DateTime) bfR.Deserialize(fsRead);
fsRead.Close();
Console.WriteLine(data);
Console.ReadKey();
The runtime proceeds through the deserialization process sequentially, starting at the beginning and working its way through to the end. The process gets complicated if an object in the serialized stream refers to another object. If an object references another object, the Formatter queries the ObjectManager to determine whether the referenced object has already been deserialized (a backward reference), or whether it has not yet been deserialized (a forward reference). If it is a backward reference, the Formatter immediately completes the reference. However, if it is a forward reference, the Formatter registers a fixup with the ObjectManager. A fixup is the process of finalizing an object reference after the referenced object has been deserialized. Once the referenced object is deserialized, ObjectManager completes the reference.
Class can be Serialized and Deserialized by adding Serializable attribute to the class. When your class is serializable run time its all the attribute will be serialized include private variable .
[Serializable]
class ShoppingCartItem
{
public int ProductID;
public string ProductName;
public decimal Quantity;
private decimal total;
public decimal price;
public ShoppingCartItem(int _productId, string _productName, decimal _Quantity, decimal _price)
{
ProductID = _productId;
ProductName = _productName;
Quantity = _Quantity;
price =_price;
total = Quantity * price;
}
}
Above class all the attribute will be serialized. In the total calculated in the dynamic. So that we no need to serialzed total. Then we can reduced the storage, bandwith requairement when object are serialized.
Use following way to nonSerialized to attribute in the class.
[NonSerialized] public decimal total;
When deserialized total does not be initialized. So that we need to calculated total before deserialized. We can be used initialized non serialized object before deserialized use IDeserializationCallback interface and implement IDeserializationCallback.OnDeserialization method.
[Serializable]
class ShoppingCartItem : IDeserializationCallback
{
public int ProductID;
public string ProductName;
public decimal Quantity;
[NonSerialized] public decimal total;
public decimal price;
public ShoppingCartItem(int _productId, string _productName, decimal _Quantity, decimal _price)
{
ProductID = _productId;
ProductName = _productName;
Quantity = _Quantity;
price =_price;
total = Quantity * price;
}
void IDeserializationCallback.OnDeserialization(Object sender)
{
total = Quantity * price;
}
}
XML Serialization
Benefits for Xml serialization -: Interoperability, Administration Friendly, forward Compatibility
Limitation -: can serialized only public data, private data cannot be serialized. Only object can be serialized, object graph cannot be serialized.
Step to Xml Serialization:
- Create a stream, textwriter or xmlWriter object to hold serialized output.
- Create XMlSerializer object
- Call XMLSerializer.serializ method to serialized object.
- Deserialized object call XmlSerializer.Deserialized method to deserialized object.
When class serialization you have to follow following task instead of other other serialization method.
Ø Class should be specified it as Public.
Ø Specified all members that be serialized as public. (Because private and protected member does not serialized when the xmlserialization. )
Ø Create a parameterless constructor.
Ex : -
This is also same manner others serialization use following changes to serialized object instead of binary /soap Formatter Serializations.
//SoapFormatter bf = new SoapFormatter();
XmlSerializer bf = new XmlSerializer(typeof(ShoppingCartItem));
You can create xml document as specific standard format using XMl Serialization attributes. Use the Xsd.exe tool to create a class that will automatically conform to an XML schema when serialized. More details to generate class using xml file follow this link
Serialized dataset using xml schema
public static void serializedDataSet()
{
FileStream fsR = new FileStream("DataSet.dat", FileMode.Create);
XmlSerializer bfr = new XmlSerializer(typeof(DataSet));
DataSet ds = new DataSet("myDataSet");
DataTable t = new DataTable("table1");
DataColumn c = new DataColumn("col1");
DataColumn c = new DataColumn("col2");
t.Columns.Add(c);
ds.Tables.Add(t);
DataRow r;
for (int i = 0; i < 10; i++)
{
r = t.NewRow();
r[0] = " row " + i;
t.Rows.Add(r);
}
TextWriter writer = new StreamWriter(fsR);
bfr.Serialize(writer, ds);
writer.Close();
}
Implement Custom Serialization
Custom serialization can be use implementing Iserializable interface and applied Serializable attribute to the class.
[Serializable]
public class ShoppingCartItem :ISerializable
{
public int ProductID;
public string ProductName;
public decimal Quantity;
[NonSerialized]public decimal total;
public decimal price;
public ShoppingCartItem(int _productId, string _productName, decimal _Quantity, decimal _price)
{
ProductID = _productId;
ProductName = _productName;
Quantity = _Quantity;
price =_price;
total = Quantity * price;
}
// The following constructor is for deserialization
protected ShoppingCartItem(SerializationInfo info, StreamingContext context)
{
ProductID = info.GetInt32("ProductID");
price = info.GetDecimal("price");
Quantity = info.GetDecimal("Quantity");
ProductName = info.GetString("ProductName");
total = price * Quantity;
}
[OnSerializing]
void CalculateTotal(StreamingContext sc)
{
total = price * Quantity;
}
[OnDeserialized]
void CheckTotal(StreamingContext sc)
{
if (total == 0) { CalculateTotal(sc); }
}
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("ProductID", ProductID);
info.AddValue("price", price);
info.AddValue("Quantity", Quantity);
info.AddValue("ProductName", ProductName);
}
Events are supported only for BinaryFormatter serialization. For SoapFormatter or custom serialization, you are limited to using the IDeserializationCallback interface.
The StreamingContext can provide information about the destination of a serialized object to classes that implement the ISerializable interface. StreamingContext is passed to both GetObjectData and an object’s serialization constructor. The Streaming Context structure has two properties those are context and state. Custome can be implement as IFormatter or IGenaricFormatter interface.
Methods that are called in response to a serialization event must accept a StreamingContext object as a parameter and are not required to accept a SerializationInfo parameter. Methods that are called in response to a serialization event must return void.