As its name suggests, XML serialization is the process of serializing an object into XML format. Quite luckily, the format of the XML file can be massively customized, so be prepared for dumb questions, like which XML file well be the output of this code, or the reverse (even better).
The classes of XML serialization lives in the System.Xml.Serialization namespace. No reference needed, because this namespace is part of the System.Xml.dll, which is linked by Visual Studio for every project.
The main class here is XmlSerializer. Now this class has absolutely nothing to do with the previous formatter classes. It has three useful instance methods, namely Serialize, Deserialize and CanSerialize. Yes, CanSerialize needs an XmlReader and returns true if the read XML file can be serialized by the instance. The Deserialize method is essentially the same as it was at the formatter classes, can read any kind of Stream, or Reader classes (XmlReader included!). However, the Serialize method is very different from the others. It takes a type (only include a single type when you are working with an Object-derived type with no is-a, has-a relationships), and an array of types, for the respective is-a, has-a relationships. Yes, you need to include every single type that participates in your object’s life.
This objective covers the use of the BinaryFormatter and SoapFormatter classes. I frankly don’t understand why they should be separated from the rest, with a title of custom serialization, but I guess we should just learn it.
These classes lives in the System.Runtime.Serialization.Formatters namespace. Even better, BinaryFormatter lives in the Binary namespace, and SoapFormatter in the Soap namespace. You will need to set a reference on the System.Runtime.Serialization.Formatters.Soap namespace in order to use the SoapFormatter class. BinaryFormatter is included by default.
BinaryFormatter serializes or deserializes yoir objects into a binary object graph. It will need two things to do so: a stream (not necessary a file stream) and an object, marked as Serializable. By default, all public fields and properties are serialized (and private fields with public properties). You can override this setting by mark your fields with the NonSerializable or OptionalField attribute. The latter is useful when dealing with version-compatible serialization.
Serialization is the process of persisting the current state of an object into a stream in such a way that it contains all information to be deserialized into the same object when needed. You’d do this typically when you’re dealing with remoting services, or when working with web services.
There are two types of serialization in the .NET Framework:
- Serialization by creating object graphs
- XML serialization
The .NET Framework provides a set of classes to work with the file system, thus creating, modifying and opening files, directories, monitoring changes, etc. These classes live in the System.IO namespace. Here’s a brief list of them, and what they are capable of:
|Classes of System.IO|
|DriveInfo Class||Provides information about installed drives on the system.|
|Directory Class||Static class with static methods to work with the directory system.|
|DirectoryInfo Class||A class to work with the directory system through instances of it.|
|File Class||Static class with static methods to work with the file system.|
|FileInfo Class||A class to work with the file system thorough instances of it.|
|FileSystemInfo Class||The base class of DirectoryInfo and FileInfo. Use it when you work with both, or extend it.|
|FileSystemWatcher Class||Look for changes in a given location, and forwards them to your code.|
There are a bunch of reader/writer classes shipped with the .NET Framework. They inherit most of their functionality from the abstract TextReader/TextWriter class (except BinaryReader/Writer).
TextReader defines the following virtual methods:
- Peek: allows you to view the next character in a stream without advancing the cursor of the given reader class.
- Read: reads the next character from the stream and advances the cursor, too.
- Read(char buffer, int index, int count): reads the characters between the specified index position and count-1.
- ReadBlock: does exactly the same what the previous overload of Read.
- ReadLine: reads a line from the current stream.
- ReadToEnd: reads the current stream to the end.
TextWriter defines the following virtual methods:
- Flush: forces the content of the buffer to be written to the underlying device, thus clears it.
- Write: with 17 overloads, each one for writing a specific type.
- WriteLine: 18 overloads, each one for writing a specific type, and ending the line with the defined NewLine string.
In this post we’ll examine the topics of compressing data, and the usage of the Isolated Storage feature of the .NET Framework. The namespaces are System.IO.Compression and System.IO.IsolatedStorage.
That’s an easy one, you’ll need to know two classes and an enumeration, namely: GZipStream, DeflateStream and CompressionMode. Even better GzipStream and DeflateStream can be used in the exact same way. The main difference, as you’d guess is the compression method. Both classes derives from Stream, so you can call the Read, Write and Seek methods. Both of them provides two constructors: the first one accepts a stream and a member of the CompressionMode enumeration. The second extends the first with a Boolean that indicates whether or not the stream should be kept open.
There are four stream classes you should be very familiar:
Stream is the abstract base class for any of the Stream classes. You can also use it to derive your custom classes. Stream exposes basic reading, writing and seeking functionality. If you aren’t sure that a given stream-derived class is able to perform these tasks, you can check at the appropriate Can Boolean properties (CanSeek, CanRead and CanWrite).
When you have finished your work with streams, you should call the Close method, which takes care of releasing resources. When you are working with a stream which has an underlying device (a file for example) you can call the Flush method, which clears all data from the stream into the underlying device.