System.Object represents a complete tree of objects. Given this, if we pass in an object that has been marked as [Serializable] and contains other [Serializable] objects, the entire set of objects is persisted in a single method call. As luck would have it, most of the types you find in the System.Collections and System.Collections.Generic namespaces have already been marked as [Serializable]. Therefore, if we wish to persist a set of objects, simply add the desired set to the container (such as an ArrayList or a List<T>) and serialize the object to your stream of choice.
First Example Code:
Now assume that we want to update the MyLuxuryCar class with a two-argument constructor, so we can set a few pieces of state data:
[Serializable, XmlRoot(Namespace = "https://mushfiqrazib.wordpress.com")] public class MyLuxuryCar : Car { public MyLuxuryCar() { } public MyLuxuryCar(bool canJump, bool isWaterProof) { CanJump = canJump; hasWaterProofSystem = isWaterProof; } [XmlAttribute(AttributeName = "CanFly")] public bool CanJump; public bool hasWaterProofSystem; }
With this, we can now persist any number of MyLuxuryCar objects:
private static void Main(string[] args) { string PersistingXMLFileName = "MyLuxuryFerrariCollection.xml"; List myCarList = new List(); myCarList.Add(new MyLuxuryCar(true, true)); myCarList.Add(new MyLuxuryCar(true, false)); myCarList.Add(new MyLuxuryCar(false, true)); myCarList.Add(new MyLuxuryCar(false, false)); // Serialize myCar object. SaveObjectAsXmlFormat(myCarList, PersistingXMLFileName); // Deserialize myCar object from the xml file DeserializeObjectFromXMLFormat(myCarList, PersistingXMLFileName); Console.Read(); } static void SaveObjectAsXmlFormat(object objGraph, string fileName) {// Save object to a file in XML format. XmlSerializer xmlFormatter = new XmlSerializer(objGraph.GetType()); using (StreamWriter writer = new StreamWriter(fileName)) { Console.WriteLine("<<>>"); xmlFormatter.Serialize(writer, objGraph); Console.WriteLine("Object list saved to xml"); } }
After the serialization, the collection objects state information into the xml file will be shown below:
<?xml version=”1.0″ encoding=”utf-8″?>
<ArrayOfMyLuxuryCar xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>
<MyLuxuryCar CanFly=”true”>
<hasAutomaticWeaponSystem xmlns=”https://mushfiqrazib.wordpress.com”>
false </hasAutomaticWeaponSystem>
<hasWaterProofSystem xmlns=”https://mushfiqrazib.wordpress.com”> true </hasWaterProofSystem>
</MyLuxuryCar>
<MyLuxuryCar CanFly=”true”>
<hasAutomaticWeaponSystem xmlns=”https://mushfiqrazib.wordpress.com”>false</hasAutomaticWeaponSystem>
<hasWaterProofSystem xmlns=”https://mushfiqrazib.wordpress.com”>false</hasWaterProofSystem>
</MyLuxuryCar>
<MyLuxuryCar CanFly=”false”>
<hasAutomaticWeaponSystem xmlns=”https://mushfiqrazib.wordpress.com”> false </hasAutomaticWeaponSystem>
<hasWaterProofSystem xmlns=”https://mushfiqrazib.wordpress.com”> true </hasWaterProofSystem>
</MyLuxuryCar>
<MyLuxuryCar CanFly=”false”>
<hasAutomaticWeaponSystem xmlns=”https://mushfiqrazib.wordpress.com”> false </hasAutomaticWeaponSystem>
<hasWaterProofSystem xmlns=”https://mushfiqrazib.wordpress.com”> false </hasWaterProofSystem>
</MyLuxuryCar>
</ArrayOfMyLuxuryCar>
In the ControlledXMLSerializationTest class, we also define DeserializeObjectFromXMLFormat method given below for deserialization of the collection objects which are now stored in the xml file. After calling the method from the main method, it shows the number of collections of MyLuxuryCar is 4.
static void DeserializeObjectFromXMLFormat(object objGraph, string filename) { XmlSerializer xmlFormatter = new XmlSerializer(objGraph.GetType()); using (StreamReader reader = new StreamReader(filename)) { Console.WriteLine("<<>>"); List myCarList = (List)xmlFormatter.Deserialize(reader); Console.WriteLine("Object list generated from xml. TOtal cars : {0}",myCarList.Count); } }
Second Example Code:
Suppose we have a Department class and Employee class. We can list employees of a department and want to store the information in a xml file. In the below code snippet two classes are defined:
[Serializable] public class Department { public string Name { get; set; } public List Employees { get; set; } public Department() { Employees = new List(); } } [Serializable] public class Employee { public string Name { get; set; } public Employee() { } public Employee(string name) { Name = name; } }
And for serialization, in the main method, we use the following code :
string PersistingXMLFileForEmployee = "EmployeeCollection.xml"; Department dept = new Department(); dept.Name = "IT"; dept.Employees.Add(new Employee("Razib")); dept.Employees.Add(new Employee("Rakib")); dept.Employees.Add(new Employee("Mushfiq")); SaveObjectAsXmlFormat(dept, PersistingXMLFileForEmployee); Console.Read();
And the generated xml file is given below:
<?xml version=”1.0″ encoding=”utf-8″?>
<Department xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>
<Name>IT</Name>
<Employees>
<Employee>
<Name> Razib</Name>
</Employee>
<Employee>
<Name>Rakib</Name>
</Employee>
<Employee>
<Name>Mushfiq</Name>
</Employee>
</Employees>
</Department>
XmlArray
The first attribute we will consider is XmlArray. This can be applied to properties that are declared as arrays or collections. It modifies the outer XML element for the property. A common use for this attribute is modifying the name of the outer element. In the Department class below, the XmlArray attribute has been applied to the Employees list. This changes the name of the generated collection element.
[Serializable] public class Department { public string Name { get; set; } [XmlArray("Staff")] public List Employees { get; set; } public Department() { Employees = new List(); } }
After serialization you can see that the Employees element has been renamed to “Staff”.
<?xml version=”1.0″ encoding=”utf-8″?>
<Department xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>
<Name>IT</Name>
<Staff>
<Employee>
<Name>Razib</Name>
</Employee>
<Employee>
<Name>Rakib</Name>
</Employee>
<Employee>
<Name>Mushfiq</Name>
</Employee>
</Staff>
</Department>
XmlArrayItem
The XmlArrayItem attribute is used to modify the inner elements that each represent an item from the collection. If we want to use a custom name for the elements instead of the data type, we can provide it in a similar manner as with XmlArray. In the following updated Department class the attribute specifies that the inner elements should be named, “StaffMember”. The XmlArray attribute is also present.
[Serializable] public class Department { public string Name { get; set; } [XmlArray("SoftwareEngineers")] [XmlArrayItem("SoftwareDeveloper")] public List Employees { get; set; } public Department() { Employees = new List(); } }
Resulting xml file will be:
<?xml version=”1.0″ encoding=”utf-8″?>
<Department xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”>
<Name>IT</Name>
<SoftwareEngineers>
<SoftwareDeveloper>
<Name>Razib</Name>
</SoftwareDeveloper>
<SoftwareDeveloper>
<Name>Rakib</Name>
</SoftwareDeveloper>
<SoftwareDeveloper>
<Name>Mushfiq</Name>
</SoftwareDeveloper>
</SoftwareEngineers>
</Department>
The full code snippet is given below:
public class ControlledXMLSerializationTest { private static void Main(string[] args) { string PersistingXMLFileName = "MyLuxuryFerrariCollection.xml"; List myCarList = new List(); myCarList.Add(new MyLuxuryCar(true, true)); myCarList.Add(new MyLuxuryCar(true, false)); myCarList.Add(new MyLuxuryCar(false, true)); myCarList.Add(new MyLuxuryCar(false, false)); // Serialize myCar object. SaveObjectAsXmlFormat(myCarList, PersistingXMLFileName); // Deserialize myCar object from the xml file DeserializeObjectFromXMLFormat(myCarList, PersistingXMLFileName); string PersistingXMLFileForEmployee = "EmployeeCollection.xml"; Department dept = new Department(); dept.Name = "IT"; dept.Employees.Add(new Employee("Razib")); dept.Employees.Add(new Employee("Rakib")); dept.Employees.Add(new Employee("Mushfiq")); SaveObjectAsXmlFormat(dept, PersistingXMLFileForEmployee); Console.Read(); } static void SaveObjectAsXmlFormat(object objGraph, string fileName) { // Save object to a file in XML format. XmlSerializer xmlFormatter = new XmlSerializer(objGraph.GetType()); using (StreamWriter writer = new StreamWriter(fileName)) { Console.WriteLine("<<>>"); xmlFormatter.Serialize(writer, objGraph); Console.WriteLine("Object list saved to xml"); } } static void DeserializeObjectFromXMLFormat(object objGraph, string filename) { XmlSerializer xmlFormatter = new XmlSerializer(objGraph.GetType()); using (StreamReader reader = new StreamReader(filename)) { Console.WriteLine("<<>>"); List myCarList = (List)xmlFormatter.Deserialize(reader); Console.WriteLine("Object list generated from xml. TOtal cars : {0}",myCarList.Count); } } } [Serializable] public class Car { public bool hasAutomaticWeaponSystem; private int crashesNo = 0; private int RunningMiles = 50; public string Model { get; set; } public string Color { get; set; } public void AddCrashes(int crashes) { crashesNo += crashes; } public void AddMiles(int miles) { RunningMiles += miles; } public override string ToString() { return String.Format(@"Car Info: Model -> {0}, Color -> {1}, Traveling -> {2}, Crash(es) - > {3}, Weapon System -> {4}", Model, Color, RunningMiles, crashesNo, hasAutomaticWeaponSystem); } } [Serializable, XmlRoot(Namespace = "https://mushfiqrazib.wordpress.com")] public class MyLuxuryCar : Car { public MyLuxuryCar() { } public MyLuxuryCar(bool canJump, bool isWaterProof) { CanJump = canJump; hasWaterProofSystem = isWaterProof; } [XmlAttribute(AttributeName = "CanFly")] public bool CanJump; public bool hasWaterProofSystem; } [Serializable] public class Department { public string Name { get; set; } [XmlArray("SoftwareEngineers")] [XmlArrayItem("SoftwareDeveloper")] public List Employees { get; set; } public Department() { Employees = new List(); } } [Serializable] public class Employee { public string Name { get; set; } public Employee() { } public Employee(string name) { Name = name; } } }