Solution: Serializing as XML
Take a look at the solution to the previous challenge.
We'll cover the following...
Problem statement
Creates a list of shapes, uses serialization to save it to the filesystem using XML, and then deserializes it back:
// create a list of Shapes to serializeList<Shape> listOfShapes = new(){new Circle { Colour = "Red", Radius = 2.5 },new Rectangle { Colour = "Blue", Height = 20.0, Width = 10.0 },new Circle { Colour = "Green", Radius = 8.0 },new Circle { Colour = "Purple", Radius = 12.3 },new Rectangle { Colour = "Blue", Height = 45.0, Width = 18.0 }};
Shapes should have a read-only property named Area
so that when deserialized, it can output a list of shapes, including their areas, as shown here:
List<Shape> loadedShapesXml =serializerXml.Deserialize(fileXml) as List<Shape>;foreach (Shape item in loadedShapesXml){WriteLine("{0} is {1} and has an area of {2:N2}",item.GetType().Name, item.Colour, item.Area);}
Step-by-step solution
Let’s look at our solution by comprehensively understanding it.
Let’s have a look at Program.cs
file:
using Packt.Shared; // Circle, Rectangle, Shapeusing System.Xml.Serialization; // XmlSerializerusing static System.Environment;using static System.IO.Path;// create a file path to write tostring path = Combine(CurrentDirectory, "shapes.xml");// create a list of Shape objects to serializeList<Shape> listOfShapes = new(){new Circle { Colour = "Red", Radius = 2.5 },new Rectangle { Colour = "Blue", Height = 20.0, Width = 10.0 },new Circle { Colour = "Green", Radius = 8 },new Circle { Colour = "Purple", Radius = 12.3 },new Rectangle { Colour = "Blue", Height = 45.0, Width = 18.0 }};// create an object that knows how to serialize and deserialize// a list of Shape objectsXmlSerializer serializerXml = new(listOfShapes.GetType());WriteLine("Saving shapes to XML file:");using (FileStream fileXml = File.Create(path)){serializerXml.Serialize(fileXml, listOfShapes);}WriteLine("Loading shapes from XML file:");List<Shape>? loadedShapesXml = null;using (FileStream fileXml = File.Open(path, FileMode.Open)){loadedShapesXml =serializerXml.Deserialize(fileXml) as List<Shape>;}if (loadedShapesXml == null){WriteLine($"{nameof(loadedShapesXml)} is empty.");}else{foreach (Shape item in loadedShapesXml){WriteLine($"{item.GetType().Name} is {item.Colour} and has an area of {item.Area:N2}");}}
In this file, we are initializing a List<Shape>
named listOfShapes
. The list is populated with instances of Circle
and Rectangle
objects, representing shapes. These shapes are specified with various properties, such as color, radius, height, and width. Then, we created objects that know how to serialize and deserialize a list of shape objects. After that, we check if the shapes were successfully loaded from the XML file. If they were loaded, it prints information about each shape, including its type, color, and area. If no shapes were loaded, it prints a message indicating that loadedShapesXml
is empty, meaning no shapes were deserialized.
Let’s have a look at Shape.cs
file:
using System.Xml.Serialization;namespace Packt.Shared;[XmlInclude(typeof(Circle))][XmlInclude(typeof(Rectangle))]public abstract class Shape{public string? Colour { get; set; }public abstract double Area { get; }}
Line 1: We import the System.Xml.Serialization
namespace to enable ...