Serialization and deserialization are important in the software world. You should be able to save data from memory on to persistence storage for later retrieval, or you may want to share the data to another software/framework/system/platform. In this series of articles, I will take you through simple to advanced features of serialization in the .NET world.
Serialization and Deserialization
To set the context, let’s define the terminologies. Serialization is the process of converting an object into a stream of bytes that could be transported to another layer or system. Deserialization is the process of converting the stream of bytes into a native object so that it can be consumed by downstream business processes. If your application involves custom, business entities that need to be persisted for future use, or to be consumed by other technologies (say a Java Service) etc., those entities need to be serialized before sending and deserialized after receiving from external systems. In .NET, when you create a class with a public property, the class’ instance will be automatically serialized/deserialized by the .NET Framework.
In this series of articles, we shall dive deep into serialization, how it works, and how we can implement our own serialization mechanism. To set the context and make everyone comfortable, let me start off with a simple sample. I recommend referring to the sample code along with this article to understand it entirely.
The diagram below shows the logical architecture of the sample application:
The system consists of a business entity (
Customer, in this case, with four fields) and a business logic layer (Customer BLL). Both are built into separate assemblies. I have a Windows client application that uses the entity and consumes the business logic layer. The application simply creates a customer entity, fills data from the controls, and then validates them using the business logic layer.
Consuming the business logic layer directly from the Windows client application is not strange. The object is created in the process of the Windows application, resides in there, and the system is able to consume and use it. This scenario is demonstrated in the “InProc Mode” in the Windows client application.
Crossing Boundary/Cross Process
I also developed a Web service project that wraps the business logic layer class. This layer exposes the BLL through a Web service. Remember, the BLL has methods that accept and return
Customer as a parameter. When we expose as a Web service, the types are exposed as part of the WSDL. So, when you query for the WSDL (type websitehomepage/webservicename.asmx?wsdl), you will see the
Customer as a complex type and its properties as elements with their type defined.
The Windows client application has another group “Using Web Service Proxy”, where the calls are made using the Web Service proxy. The application works fine, it is able to create the
Customer object and validate it using the Web Service. When the data is transferred through the Web service, they use XML format. The question is how the
Customer object is converted to XML and who does it? We never wrote any code to convert the object to XML and vice versa. Indeed, it is done by the .NET Framework itself.
The framework looks at the public properties of the class and coverts them using the
XmlSerializer into XML format – this is called serialization.
When it is consumed by another .NET application, the .NET framework would convert the XML stream into .NET objects automatically – this is called deserialization. This is done as a two step process. When you create a Web Service proxy using WSDL.exe or through the VS Add Web Reference option, the tool would generate a proxy class to consume the Web Service and will also create entity classes by looking at the WSDL complex types. So, once done, you would see the
CustomerService class which is your proxy class, then the
Customer class which is your entity class.
When you call the Web Service through the
CustomerService proxy class, it takes and returns a
Customer instance that is created as part of the proxy class. This is evident when you look at the WSDL generated proxy code. Refer to Reference.cs inside the Web References-> CustomerBLLWSServiceProxy folder.
How the Code Works
The download contains the following C# projects:
- BusinessEntities – contains the
Customer class with the public fields.
- BusinessLogicLayer – performs the business logic on the business entities.
- BLLWebService – the Web service project that exposes the Business Logic Layer as a Web Service.
- WinClient – the Windows Forms client application that consumes the Business Logic Layer (In proc scenario) and the BLL Web Service (outproc, cross platform scenario). The InProc Mode Validate button calls the Business Logic Layer. In this case, there will not be a serialization or a deserialization process. The Web Service Mode Validate button calls the Web service. It first calls the
NewCustomer() method, gets the
Customer instance, fills the data, and calls the
ValidateCustomer() Web Service method. This time, it passes the filled
Customer instance. The
Customer instance that it creates will be the proxy generated class and not the one from the BusinessEntities assembly.
This is an introductory article about serialization and deserialization processes. In the next article, we shall dive deep into the serialization process.
Happy reading, Happy coding!