Home

Serialization

 

Object Serialization and De-Serialization

 

Introduction

Consider the following form:

Serialization

#pragma once

namespace CarReview
{
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::IO;

---------------------------------------------------

System::Void btnWrite_Click(System::Object^  sender, System::EventArgs^  e)
{
	String ^ Make  = txtMake->Text;
    String ^ Model = txtModel->Text;
    int Year  = int::Parse(txtYear->Text);
    String ^ Color = txtColor->Text;

    FileStream ^ stmCar = gcnew FileStream("Car1.car", FileMode::Create);
    BinaryWriter ^ bnwCar = gcnew BinaryWriter(stmCar);

    try
    {
        bnwCar->Write(Make);
        bnwCar->Write(Model);
        bnwCar->Write(Year);
        bnwCar->Write(Color);
    }
    finally
    {
        bnwCar->Close();
        stmCar->Close();
    }
}

Here is an example of running the program:

Serialization

This is an example of the techniques used in file processing to save individual data of primitive types:

Saving the variables in a method

The values can be retrieved with the following code:

System::Void btnRead_Click(System::Object^  sender, System::EventArgs^  e)
{
    FileStream ^ stmCar = gcnew FileStream("Car1.car", FileMode::Open);
    BinaryReader ^ bnrCar = gcnew BinaryReader(stmCar);

    try
    {
        txtMake->Text = bnrCar->ReadString();
        txtModel->Text = bnrCar->ReadString();
        txtYear->Text = bnrCar->ReadUInt32().ToString();
        txtColor->Text = bnrCar->ReadString();
    }
    finally
    {
        bnrCar->Close();
        stmCar->Close();
    }
}

In the same way, you can save the individual fields of a class or you can retrieve the individual fields of a car:

Saving the individual parts of an object

Here is an example:

ref class CCar
{
public:
    String ^ Make;
    String ^ Model;
    int Year;
    String ^ Color;
};

private:
    System::Void btnWrite_Click(System::Object^  sender, System::EventArgs^  e)
    {
    	CCar ^ vehicle = gcnew CCar;

        vehicle->Make  = txtMake->Text;
        vehicle->Model = txtModel->Text;
        vehicle->Year  = int::Parse(txtYear->Text);
        vehicle->Color = txtColor->Text;

        FileStream ^ stmCar = gcnew FileStream("Car2.car", FileMode::Create);
        BinaryWriter ^ bnwCar = gcnew BinaryWriter(stmCar);

        try
        {
            bnwCar->Write(vehicle->Make);
            bnwCar->Write(vehicle->Model);
            bnwCar->Write(vehicle->Year);
            bnwCar->Write(vehicle->Color);
        }
        finally
        {
            bnwCar->Close();
            stmCar->Close();
        }
    }

    System::Void btnRead_Click(System::Object^  sender, System::EventArgs^  e)
    {
	FileStream ^ stmCar = gcnew FileStream("Car2.car", FileMode::Open);
        BinaryReader ^ bnrCar = gcnew BinaryReader(stmCar);

        try
        {
            CCar ^ vehicle = gcnew CCar;

            vehicle->Make = bnrCar->ReadString();
            vehicle->Model = bnrCar->ReadString();
            vehicle->Year = bnrCar->ReadUInt32();
            vehicle->Color = bnrCar->ReadString();

            txtMake->Text = vehicle->Make;
            txtModel->Text = vehicle->Model;
            txtYear->Text = vehicle->Year.ToString();
            txtColor->Text = vehicle->Color;
        }
        finally
        {
            bnrCar->Close();
            stmCar->Close();
        }
    }
};
}

When it comes to a class, the problem with saving individual fields is that you could forget to save one of the fields. For example, considering a CCar class, if you don't save the Make information of a CCar object and retrieve or open the saved object on another computer, the receiving user would miss some information and the car cannot be completely identifiable. An alternative is to save the whole CCar object.

Object serialization consists of saving a whole object as one instead of its individual fields:

Serialization

In other words, a variable declared from a class can be saved to a stream and then the saved object can be retrieved later or on another computer. The .NET Framework supports two types of object serialization: binary and SOAP.

Practical Learning: Introducing Serialization

  1. Start Microsoft Visual Studio
  2. To start a new project, on the main menu, click File -> New Project...
  3. In the middle list, click Windows Forms Application
  4. Set the Name to SchoolCatalog1
  5. Click OK
  6. To create a new form, on the main menu, click Project -> Add New Item...
  7. In the middle list, make sure Windows Form is selected.
    Set the Name to CourseEditor
  8. Click Add
  9. Design the form as follows:
     
    School Catalog
    Control (Name) DialogResult Text Modifiers
    Label Label     Course Code:  
    TextBox TextBox txtCourseCode     Public
    Label Label     Credits:  
    TextBox TextBox txtCredits   1 Public
    Label Label     Course Name:  
    TextBox TextBox txtCourseName      Public
    Button Button btnOK OK OK  
    Button Button btnCancel Cancel Cancel  
    Form
    FormBorderStyle: FixedDialog
    Text: University Catalog - Course Editor
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  10. Display the first form and design it as follows:
     
    School Catalog
    Control (Name) Anchor Text
    DataGridView DataGridView dgvCourseCataglog Top, Bottom, Left, Right  
    Columns  
    Header Text Name Width
    Course Code CourseCode  
    Course Name CourseName 200
    Credits Credits 60
    Button btnNewCourse Bottom, Left &New Course
    Button btnClose Bottom, Right &Close
    Form
    Text: University Catalog - Course Catalog
    StartPosition: CenterScreen

Serialization

Binary serialization works by processing an object rather than streaming its individual member variables. This means that, to use it, you define an object and initialize it, or "fill" it, with the necessary values and any information you judge necessary. This creates a "state" of the object. It is this state that you prepare to serialize. When you save the object, it is converted into a stream.

To perform binary serialization, there are a few steps you must follow. When creating the class whose objects would be serialized, start it with the [Serializable] attribute. Here is an example:

[Serializable]
public ref class CCar
{
public:
    String ^ Make;
    String ^ Model;
    int Year;
    String ^ Color;
};

Before serializing an object, you should reference the System::Runtime::Serialization::Formatters::Binary namespace. The class responsible for binary serialization is called BinaryFormatter. This class is equipped with two constructors. The default constructor is used to simply create an object.

After declaring the variable, to actually serialize an object, call the Serialize() member function of the BinaryFormatter class. The member function is overloaded with two versions. One of the versions of this member function uses the following syntax:

public:
    virtual void Serialize(Stream^ serializationStream,
    			   Object^ graph) sealed;

The first argument to this member function must be an object of a Stream-based class, such as a FileStream object. The second argument must be the object to serialize. This means that, before calling this member function, you should have built the object.

Here is an example:

#pragma once

namespace CarReview {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::IO;
    using namespace System::Runtime::Serialization::Formatters::Binary;

    [Serializable]
    ref class CCar
    {
    public:
        String ^ Make;
        String ^ Model;
        int Year;
        String ^ Color;
    };

--------------------------------------------------------------------

System::Void btnWrite_Click(System::Object^  sender, System::EventArgs^  e)
{
    CCar ^ vehicle = gcnew CCar;

    vehicle->Make  = txtMake->Text;
    vehicle->Model = txtModel->Text;
    vehicle->Year  = int::Parse(txtYear->Text);
    vehicle->Color = txtColor->Text;

    FileStream ^ stmCar = gcnew FileStream("Car3.car",
                                           FileMode::Create);
    BinaryFormatter ^ bfmCar = gcnew BinaryFormatter;

    bfmCar->Serialize(stmCar, vehicle);
}

Practical Learning: Serializing an Object

  1. To create a new class, on the main menu, click Project -> Add Class...
  2. In the middle list, click C++ Class
  3. Click Add
  4. Set the Name to CCourse
     
    Generic C++ Class Wizard
  5. Click Finish
  6. Change the header file as follows:
    #pragma once
    
    using namespace System;
    
    [Serializable]
    public ref class CCourse
    {
    public:
        CCourse(void);
    
        String ^ CourseCode;
        String ^ CourseName;
        int      Credits;
    };
  7. On the main menu, click Windows -> Form1.h [Design]*
  8. Right-click the form and click View Code
  9. In the top section of the file, add a reference to the System::IO, the Collections::Generic, and the Formatters::Binary namespaces
  10. Also, declare a List<> variable named courses:
    #pragma once
    
    #include "Course.h"
    #include "CourseEditor.h"
    
    namespace SchoolCatalog1 {
    
        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;
        using namespace System::IO;
        using namespace System::Collections::Generic;
        using namespace System::Runtime::Serialization::Formatters::Binary;
    
        /// <summary>
        /// Summary for Form1
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        private:
            List<CCourse ^> ^ courses;
  11. Return to the main menu and double-click an unoccupied area of its body
  12. Initialize the courses variable as follows:
    System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
    {
        courses = gcnew List<CCourse ^>;
    }
  13. Return to the form

De-Serialization

As serialization is the process of storing an object to a medium, the opposite, serialization is used to retrieve an object from a stream. To support this, the BinaryFormatter class is equipped with the Deserialize() member function. Like Serialize(), the Deserialize() member function is overloaded with two versions. One of them uses the following syntax:

public:
    virtual Object^ Deserialize(Stream^ serializationStream) sealed;

This member function takes as argument a Stream-based object, such as a FileStream variable, that indicates where the file is located. The Deserialize() member function returns an Object object. As a goal, you want the Deserialize() member function to produce the type of object that was saved so you can retrieve the values that the returned object holds. Because the member function returns an Object value, you must cast the returned value to the type of your class.

Once the Deserialize() member function has returned the desired object, you can access its values. Here is an example:

System::Void btnRead_Click(System::Object^  sender, System::EventArgs^  e)
{
    FileStream ^ stmCar = gcnew FileStream("Car3.car",
                                           FileMode::Open);
    BinaryFormatter ^ bfmCar = gcnew BinaryFormatter;
    CCar ^ vehicle = (CCar ^)bfmCar->Deserialize(stmCar);

    txtMake->Text = vehicle->Make;
    txtModel->Text = vehicle->Model;
    txtYear->Text = vehicle->Year.ToString();
    txtColor->Text = vehicle->Color;
}

Practical Learning: De-Serializing an Object

  1. On the form, double-click New Course...
  2. Return to the form and double-click the Close button
  3. Change the file as follows:
    void ShowCourses()
    {
        // Get a reference to the file that holds the courses
        String ^ Filename = "C:\\School Catalog\\courses.sct";
    
        // Make sure the file exists
        if( File::Exists(Filename) == true)
        {
            // if so, create a file stream
            FileStream ^ stmCourses = gcnew FileStream(Filename,
                                                       FileMode::Open,
                                                       FileAccess::Read);
            // Create a binary formatter
            BinaryFormatter ^ bfmCourse = gcnew BinaryFormatter;
            // If some courses were created already,
            // get them and store them in the collection
            courses = (List<CCourse ^> ^)bfmCourse->Deserialize(stmCourses);
    
            // Prepare to show the list of courses
            int i = 0;
            // First, empty the data grid view
            dgvCourseCataglog->Rows->Clear();
    
            // Visit each course in the collection and add it to the data grid view
            for each(CCourse ^ study in courses)
            {
                dgvCourseCataglog->Rows->Add();
    
                dgvCourseCataglog->Rows[i]->Cells[0]->Value = study->CourseCode;
                dgvCourseCataglog->Rows[i]->Cells[1]->Value = study->CourseName;
                dgvCourseCataglog->Rows[i]->Cells[2]->Value =
                		study->Credits.ToString();
                i++;
            }
    
            // Close the file stream
            stmCourses->Close();
        }
    }
    
    System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
    {
        courses = gcnew List<CCourse ^>;
    	ShowCourses();
    }
    
    System::Void btnNewCourse_Click(System::Object^  sender, System::EventArgs^  e)
    {
        // Get a reference to the course editor
        CourseEditor ^ editor = gcnew CourseEditor;
        // Check that the directory that contains the list of courses exists.
        // If it doesn't exist, create it
        DirectoryInfo ^ dirInfo = Directory::CreateDirectory("C:\\School Catalog");
        // Get a reference to the file that holds the courses
        String ^ Filename = "C:\\School Catalog\\courses.sct";
    
        // First check if the file was previously created
        if( File::Exists(Filename) == true)
        {
            // If the list of courses exists already,
            // get it and store it in a file stream
            FileStream ^ stmCourses = gcnew FileStream(Filename,
                                                       FileMode::Open,
                                                       FileAccess::Read);
            BinaryFormatter ^ bfmCourse = gcnew BinaryFormatter;
            // Store the list of courses in the collection
            courses = (List<CCourse ^> ^)bfmCourse->Deserialize(stmCourses);
            // Close the file stream
            stmCourses->Close();
        }
    
        // Display the Course Editor
        if( editor->ShowDialog() == System::Windows::Forms::DialogResult::OK )
        {
            // Get each value of the new course.
            // Create a Course object from it
            CCourse ^ study = gcnew CCourse;
            study->CourseCode = editor->txtCourseCode->Text;
            study->CourseName = editor->txtCourseName->Text;
            study->Credits    = int::Parse(editor->txtCredits->Text);
            // Add the course in the collection
            courses->Add(study);
    
            // Get a reference to the courses file
            String ^ strFilename = dirInfo->FullName + "\\\courses.sct";
            // Create a file stream to hold the list of courses
            FileStream ^ stmCourses = gcnew FileStream(strFilename,
                                                       FileMode::Create,
                                                       FileAccess::Write);
            BinaryFormatter ^ bfmCourses = gcnew BinaryFormatter;
    
            // Serialize the list of courses
            bfmCourses->Serialize(stmCourses, courses);
            // Close the file stream
            stmCourses->Close();
        }
    
        // Show the list of courses
        ShowCourses();
    }
    
    System::Void btnClose_Click(System::Object^  sender, System::EventArgs^  e)
    {
    	Close();
    }
  4. Execute the application and continuously click the New Course button to create the following courses:
     
    School Catalog
     
    Course Code Course Name Credits
    CMSC 101 Introductory Computer Science 3
    ENGL 101 Introduction to English 3
    BMGT 324 Introduction to Entrepreneurship: Starting a Small Business 1
    BIOL 160 Human Biology 3
    BMGT 110 Introduction to Business and Management 3
    CMSC 150 Introduction to Discrete Structures 3
    CMSC 330 Advanced Programming Languages 3
    CHEM 121 Chemistry in the Modern World 3
     
    School Catalog

  5. Close the form and return to your programming environment
 
 
 

SOAP Serialization

 

Introduction

The .NET Framework supports another technique of serialization referred to as SOAP (which stands for Simple Object Access Protocol). This technique is related to XML but, although we haven't studied XML, you don't need to know anything about it to use SOAP serialization.

Practical Learning: Introducing SOAP Serialization

  1. To start a new application, on the main menu, click File -> New Project...
  2. In the middle list, click Windows Forms Application
  3. Set the Name to RealEstate1
  4. Click OK
  5. To create a new form, on the main menu, click Projects -> Add New Item...
  6. In the middle list, make sure Windows Form is selected.
    Set the Name to PropertyEditor
  7. Click Add
  8. Design the form as follows:
     
    Real Estate
    Control (Name) BorderStyle DialogResult Enabled Text Modifiers
    Label Label         Property #:  
    TextBox TextBox txtPropertyNumber     False   Public
    Label Label         Market Value:  
    TextBox TextBox txtMarketValue       0.00 Public
    Label Label         Property Type:  
    TextBox TextBox txtPropertyTypes          Public
    Label Label         City:  
    TextBox TextBox txtCity         Public
    Label Label         State:  
    TextBox TextBox cbxStates         Public
    Label Label         Bedrooms:  
    TextBox TextBox txtBedrooms       0 Public
    Label Label         Bathrooms:  
    TextBox TextBox txtBathrooms       0.00 Public
    Button Button btnOK   OK   OK  
    Button Button btnCancel   Cancel   Cancel  
    Form
    FormBorderStyle: FixedDialog
    Text: Altair Realtors - Property Editor
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  9. Display the first form and design it as follows:
     
    Altair Realtors
    Control (Name) Anchor Text
    DataGridView DataGridView dgvProperties Top, Bottom, Left, Right  
    Columns  
    Header Text Name Width
    Prop# PropertyNumber 80
    Property Type PropertyType 120
    City City  
    State State 50
    Beds Bedrooms 50
    Bathrooms Bathrooms 50
    Market Value MarketValue  
    Button btnNewProperty Bottom, Left btnNewProperty
    Button Close Bottom, Right btnClose
    Form
    Text: Altair Realtors - Properties Listing
    StartPosition: CenterScreen

Serialization With SOAP

To serialize an object using SOAP, you follow the same steps we reviewed for the binary serialization with one addition: you must add a certain reference.

When creating the class whose objects would be serialized, mark it with the [Serializable] attribute. Here is an example:

[Serializable]
public ref class CCar
{
public:
    String ^ Make;
    String ^ Model;
    int      Year;
    String ^ Color;
};

To support SOAP serialization, the .NET Framework provides the SoapFormatter class. This class is defined in the System::Runtime::Serialization::Formatters::Soap namespace that is part of the System.Runtime.Serialization.Formatters.Soap.dll library. In order to use The SoapFormatter class, you must reference this assembly. You can create an object and initialize it as you see fit. Before saving it, as always, create a Stream-based object that would indicate the name (and location) of the file and the type of action to perform. Then, declare a SoapFormatter variable using its default constructor. To actually save the object, call the Serialize() member function of this class. This member function uses the same syntax as that of the BinaryFormatter class: it takes two arguments. The first is a Stream-based object. The second is the object that needs to be serialized.

Practical Learning: Serializing With SOAP

  1. To create a new class, on the main menu, click Project -> Add Class...
  2. In the middle list, click C++ Class and click Add
  3. Set the Name to CEstateProperty
  4. Click Finish
  5. Change the file as follows:
    #pragma once
    
    using namespace System;
    
    [Serializable]
    public ref class CEstateProperty
    {
    public:
        CEstateProperty(void);
    
        String ^ PropertyNumber;
        String ^ PropertyType;
        String ^ City;
        String ^ State;
        short    Bedrooms;
        float    Bathrooms;
        double   MarketValue;
    };
  6. To add SOAP support to your project, on the main menu, click Project -> RealEstate1 Properties...
  7. Click Add New Reference...
  8. In the Add Reference dialog box. click the .NET tab
  9. Scroll down and select System.Runtime.Serialization.Formatters.Soap:
     
    Adding a reference to the System.Runtime.Serialization.Formatters.Soap.dll assembly
  10. Click OK
     
    Property Pages
  11. Click OK
  12. On the main menu, click Windows -> Form1.h [Design]*
  13. Right-click the form and click View Code
  14. Change the file as follows:
    #pragma once
    
    #include "EstateProperty.h"
    #include "PropertyEditor.h"
    
    namespace RealEstate1 {
    
        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;
        using namespace System::IO;
        using namespace System::Runtime::Serialization::Formatters::Soap;
    
        /// <summary>
        /// Summary for Form1
        /// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        private:
            ArrayList ^ properties;
  15. Return to the form and double-click an unoccupied area of its body
  16. Change the file as follows:
    void ShowProperties()
    {
    }
    
    System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
    {
        properties = gcnew ArrayList;
        ShowProperties();
    }
  17. Return to the form

De-Serialization With SOAP

De-serialization in soap is performed exactly as done for the binary de-serialization. To support it, the SoapFormatter class is equipped with the Deserialize() member function. This member function uses the same syntax as its equivalent of the BinaryFormatter class. The approach to use it is also the same.

Practical Learning: Deserializing With SOAP

  1. On the form, double-click New Property...
  2. Return to the form and double-click the Close button
  3. Change the file as follows:
    void ShowProperties()
    {
        // Get a reference to the file that holds the records of properties
        String ^ Filename = "C:\\Altair Realtors\\properties.prp";
    
        // Make sure the file exists
        if( File::Exists(Filename) == true )
        {
            // if so, create a file stream
            FileStream ^ stmProperties = gcnew FileStream(Filename,
                                                          FileMode::Open,
                                                          FileAccess::Read);
            // Create a soap formatter
            SoapFormatter ^ bfmProperty = gcnew SoapFormatter;
            // If some properties were created already,
            // get them and store them in the collection
            properties = (ArrayList ^)bfmProperty->Deserialize(stmProperties);
    
            // Prepare to show the list of properties
            int i = 0;
            // First, empty the data grid view
            dgvProperties->Rows->Clear();
    
            // Visit each property in the collection and add it to the data grid view
            for each(CEstateProperty ^ house in properties)
            {
                dgvProperties->Rows->Add();
    
                dgvProperties->Rows[i]->Cells[0]->Value = house->PropertyNumber;
                dgvProperties->Rows[i]->Cells[1]->Value = house->PropertyType;
                dgvProperties->Rows[i]->Cells[2]->Value = house->City;
                dgvProperties->Rows[i]->Cells[3]->Value = house->State;
                dgvProperties->Rows[i]->Cells[4]->Value = house->Bedrooms.ToString();
                dgvProperties->Rows[i]->Cells[5]->Value = house->Bathrooms.ToString("F");
                dgvProperties->Rows[i]->Cells[6]->Value = house->MarketValue.ToString("F");
                i++;
            }
    
            // Close the file stream
            stmProperties->Close();
        }
    }
    
    System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
    {
        properties = gcnew ArrayList;
        ShowProperties();
    }
    
    System::Void btnNewProperty_Click(System::Object^  sender, System::EventArgs^  e)
    {
    	// Get a reference to the property editor
        PropertyEditor ^ editor = gcnew PropertyEditor;
        // Check that the directory that contains the list of properties exists.
        // If it doesn't exist, create it
        DirectoryInfo ^ dirInfo = Directory::CreateDirectory("C:\\Altair Realtors");
        // Get a reference to the file that holds the properties
        String ^ Filename = "C:\\Altair Realtors\\properties.prp";
    
        // First check if the file was previously created
        if( File::Exists(Filename) == true )
        {
            // If the list of properties exists already,
            // get it and store it in a file stream
            FileStream ^ stmProperties = gcnew FileStream(Filename,
                                                          FileMode::Open,
                                                          FileAccess::Read);
            SoapFormatter ^ bfmProperty = gcnew SoapFormatter;
            // Store the list of properties in the collection
            properties = (ArrayList ^)bfmProperty->Deserialize(stmProperties);
            // Close the file stream
            stmProperties->Close();
        }
    
        // Generate a random number for a property
        Random ^ rnd = gcnew Random;
        int left = rnd->Next(100, 999);
        int right = rnd->Next(100, 999);
        editor->txtPropertyNumber->Text = left.ToString() + "-" + right.ToString();
    
        // Display the Property Editor
        if( editor->ShowDialog() == System::Windows::Forms::DialogResult::OK )
        {
            // Get each value of the new property.
            // Create an EstateProperty object from it
            CEstateProperty ^ prop = gcnew CEstateProperty;
    
            prop->PropertyNumber = editor->txtPropertyNumber->Text;
            prop->PropertyType = editor->txtPropertyType->Text;
            prop->City = editor->txtCity->Text;
            prop->State = editor->txtState->Text;
            prop->Bedrooms = short::Parse(editor->txtBedrooms->Text);
            prop->Bathrooms = float::Parse(editor->txtBathrooms->Text);
            prop->MarketValue = double::Parse(editor->txtMarketValue->Text);
            // Add the property in the collection
            properties->Add(prop);
    
            // Get a reference to the properties file
            String ^ strFilename = dirInfo->FullName + "\\properties.prp";
            // Create a file stream to hold the list of properties
            FileStream ^ stmProperties = gcnew FileStream(strFilename,
                                                          FileMode::Create,
                                                          FileAccess::Write);
            SoapFormatter ^ bfmProperty = gcnew SoapFormatter;
    
            // Serialize the list of properties
            bfmProperty->Serialize(stmProperties, properties);
            // Close the file stream
            stmProperties->Close();
        }
    
        // Show the list of properties
        ShowProperties();
    }
    
    System::Void btnClose_Click(System::Object^  sender, System::EventArgs^  e)
    {
    	Close();
    }
  4. Execute the application and continuously click the New Property button to create the following properties (let the computer specify the property number):
     
    Real Estate
     
    Market Value Property Type City State  Beds Baths
    375650 Single Family Baltimore MD 5 3.50
    275500 Townhouse Gettysburg WV 3 2.50
    488665 Condominium Washington DC 1 1.00
    385000 Single Family Martinsburg WV 4 3.50
    568445 Condominium Rockville MD 1 1.00
     
    Real Estate
  5. Close the form and return to your programming environment

Details on Serialization

 

Partial Serialization

In the examples we have used so far, we were saving the whole object. You can make it possible to save only some parts of the class. When creating a class, you can specify what fields would be serialized and which ones would not be. To specify that a member cannot be saved, you can mark it with the [NonSerialized] attribute. Here is an example:

[Serializable]
public ref class CVoiture
{
public:
    String ^ Make;
    String ^ Model;

    // Because the value of a car can change,
    // there is no reason to save it
    [NonSerialized]
    double Value;
    unsigned int Year;
    String ^ Color;
};

After creating the class, you can declare a variable of it and serialize it, using either the binary or the SOAP approach. You can then retrieve the object and its values, using any of the techniques we learned earlier.

Implementing a Custom Serialized Class

To support serialization, the .NET Framework provides the ISerializable interface. You can create a class that implements this interface to customize the serialization process. Even if you plan to use this interface, the class you create must be marked with the [Serializable] attribute.

.NET Built-In Serialized Classes

The .NET Framework is filled with many classes ready for serialization. To know that a class is ready for serialization, when viewing its documentation either in the MSDN web site or in the help documentation, check that it is marked with the [SerializableAttribute]. Some of the classes provide the properties and member functions to create an object and directly save it. For some other classes, you must first create a class, mark it with the [Serializable] attribute, build an object of it, and then pass it to the .NET class.

 
 
   
 

Home Copyright © 2011 FunctionX, Inc. Home