Fundamentals of Serialization

Saving Values to a Stream

In our introduction to file processing, we learned to save the values of primitive types to a stream. Here is an example:

using System.IO;

namespace FileProcessing
{
    public class Program
    {
        public static int Main(string[] args)
        {
            string fileName = "../../dischwasher.apl";

            FileStream fsAppliance = new FileStream(fileName, FileMode.OpenOrCreate,
                                                    FileAccess.ReadWrite, FileShare.ReadWrite);
            BinaryWriter bwAppliance = new BinaryWriter(fsAppliance);

            try
            {
                string make   = "EdgeStar";
                string model  = "BIDW1802SS";
                double weight = 52.9;
                double price  = 699.75;
                (double width, double height, double depth) dimensions = (22.44, 17.63, 32.5);
                
                bwAppliance.Write(make);
                bwAppliance.Write(model);
                bwAppliance.Write(weight);
                bwAppliance.Write(price);
                bwAppliance.Write(dimensions.width);
                bwAppliance.Write(dimensions.height);
                bwAppliance.Write(dimensions.depth);
            }
            finally
            {
                bwAppliance.Close();
                fsAppliance.Close();
            }

            return 100000;
        }
    }
}

If the values you want to save belong to an object (of a class), you can save the value of each property. That way, you would save the whole object one value at a time. Here is an example:

using System.IO;

namespace FileProcessing
{
    public interface IAppliance
    {
        string Make   { get; set; }
        string Model  { get; set; }
        double Price  { get; set; }
        double Weight { get; set; }
        (double Width, double Height, double Depth) Dimensions { get; set; }
    }

    public class Dishwasher : IAppliance
    {
        public string Make   { get; set; }
        public string Model  { get; set; }
        public double Price  { get; set; }
        public double Weight { get; set; }
        public (double Width, double Height, double Depth) Dimensions { get; set; }
    }

    public class Program
    {
        public static int Main(string[] args)
        {
            string fileName = "../../dischwasher2.apl";

            FileStream fsAppliance = new FileStream(fileName, FileMode.OpenOrCreate,
                                                    FileAccess.ReadWrite, FileShare.ReadWrite);
            BinaryWriter bwAppliance = new BinaryWriter(fsAppliance);

            try
            {
                Dishwasher dw = new Dishwasher()
                {
                    Make = "LG",
                    Model = "LDF5678SS",
                    Weight = 79.6,
                    Price = 612.35,
                    Dimensions = (23.75, 33.625, 24.625)
                };
                
                
                bwAppliance.Write(dw.Make);
                bwAppliance.Write(dw.Model);
                bwAppliance.Write(dw.Weight);
                bwAppliance.Write(dw.Price);
                bwAppliance.Write(dw.Dimensions.Width);
                bwAppliance.Write(dw.Dimensions.Height);
                bwAppliance.Write(dw.Dimensions.Depth);
            }
            finally
            {
                bwAppliance.Close();
                fsAppliance.Close();
            }

            return 100000;
        }
    }
}

Another operation related to file processing consists of sending values from one computer or device to another computer or device, which is done in communication applications (such as Windows Communication Foundation or WCF). The approach is the same as we saw in the previous two examples.

The above two examples work well if you are dealing with just a few values. Now, imagine that you want to save or send many values or many objects at the same time, or suppose that you want to save a long list of values or a collection of objects. It would be tedious to save one value at a time. This is where serialization comes in.

Practical LearningPractical Learning: Introducing Serialization

  1. Start Microsft Visual Studio and create a Windows Forms application named WattsALoan1
  2. To create a new class, on the main menu, click Projett -> Add Class...
  3. Type Employee as the name of the class
  4. Click Add
  5. Change the documentas follows:
    namespace WattsALoan1
    {
        public class Employee
        {
            public string EmployeeNumber { get; set; }
            public string FirstName      { get; set; }
            public string LastName       { get; set; }
            public string Title          { get; set; }
        }
    }
  6. In the Solution explorer, right-click Form1.cs and click Rename
  7. Type WattsALoan (to get WattsALoan.cs)
  8. Press Enter three times to access the form
  9. Double-click the middle of the form to create its Load event
  10. Change the document as follows:
    using System;
    using System.IO;
    using System.Windows.Forms;
    
    namespace WattsALoan1
    {
        public partial class WattsALoan : Form
        {
            public WattsALoan()
            {
                InitializeComponent();
            }
    
            private void WattsALoan_Load(object sender, EventArgs e)
            {
                /* The files for this project will reside in a directory we will create.
                 * By default, we will create a directory in a C: drive. If you are planning
                 * to use a different directory, change the value of the following variable. 
                 * In the same way, if you are working on an operating system other than 
                 * Microsoft Windows, make the necessary changes. */
                string strDrive = @"C:\";
                /* This is the main directory where the files of the project will reside.
                 * If necessary, make the appropriate changes. */
                string strPrimaryFolder = strDrive + "Watts A Loan";
    
                // Prepare the directory
                DirectoryInfo diWattsALoan = new DirectoryInfo(strPrimaryFolder);
                // Create the primary directory for this project
                diWattsALoan.Create();
    
                // A Directory for the employees files
                DirectoryInfo diEmployees = diWattsALoan.CreateSubdirectory("Employees");
                // A Directory for the loans contracts files
                diWattsALoan.CreateSubdirectory("Loans Contracts");
                // A Directory for the loans payments files
                diWattsALoan.CreateSubdirectory("Loans Payments");
            }
        }
    }

Introduction to XML Serialization

Serialization is the ability to save an object or a whole collection of objects to a stream. Another concept of serialization is the ability to send an object or a whole collection of objects from one device to another. In both cases, the object or the collection is save or sent as a whole instead of its individual values.

The .NET Framework supports various techniques to serializa. In our lessons, we will study and use only one of them.

XML serialization is the ability to save (to a medium or send through communication) an object or a collection of objects in XML format. Although the XML name is used, you really don't need to know anything about XML to use this technique or its class, but we first studied XML in previous lessons so you would know what an XML document (or its content) looks like.

Serializing and Deserializing an Object

Serializing an Object

The .NET Framework supports XML serialization through a class named XmlSerializer

public class XmlSerializer

This class is created in a namespace named System.Xml.Serialization. This namespace is defined in the System.Xml.Serialization.dll assembly. Therefore, you must make sure that your project contains a reference to the System.Xml.Serialization.dll assembly. If you create a console application or a Windows Forms application in Microsoft Visual Studio, that assembly is automatically added to your project. In a document where you want to serialize, you can add the using System.Xml.Serialization; line. Other than that, in the next sections, we will see that (once you have been introduced to file processing and know XML) XML serialization is extremely easy to use. You write just a couple of lines of code and the compiler will take care of the rest.

In our introductions to file processing, we saw that, as a preparation, you can create an object with which you will write values to a stream. This can be done by declaring a StreamWriter variable and initializing it. You can also declare a variable of the abstract TextWriter class but initialize it with the StreamWriter class. The StreamWriter class is equipped with various constructors. One of the constructors uses the following syntax:

public StreamWriter (string path);

This constructor takes as argument the name of a file or its complete path. You can first declare and initialize a string variable and then pass that variable to a StreamWriter object. Here is an example:

using System.IO;

public class Exercise
{
    public static void Main(string[] args)
    {
        string fileName = "dischwasher.apl";
        StreamWriter swAppliance = new StreamWriter(fileName);

        return;
    }
}

Of course, you can pass the name or path of the file directly to a StreamWriter variable.

To serialize an object, you must first create it, which is easily done by declaring a variable of a class (or structure) type. If one of the built-in classes of the .NET Framework suits your needs, you can use it. Otherwise, you can create a class and fill it with properties of your choice. Then, declare a variable of type XmlSerializer. This class is equipped with various constructors (nine). The first is the default constructor (it doesn't take any argument). The second constructor uses this syntax:

public XmlSerializer (Type type);

This constructor asks you to specify the type of the object you want to serialize. The type should be qualified using the typeof() operator. After creating an XmlSerializer objet, to actually serialize the object, you must associate the stream to the object to be serialized. To support this, the XmlSerializer class is equipped with a method named Serialize. This method is overloaded with nine versions. One of the versions of this method uses the following syntax:

public void Serialize(TextWriter textWriter, object o);

This method takes a TextWriter-based object as argument. The method secondly needs the object that must be written to the stream. Once you call this method, that's it, your job is done. As a small detaiul, remember that the TextWriter class implements the IDisposable interface. This means that you must close the writer after using it, and you have many options. You can:

Practical Learning: Serializing Objects

  1. To serialize some objects, change the document as follows:
    using System;
    using System.IO;
    using System.Windows.Forms;
    using System.Xml.Serialization;
    
    namespace WattsALoan1
    {
        public partial class WattsALoan : Form
        {
            public WattsALoan()
            {
                InitializeComponent();
            }
    
            private void WattsALoan_Load(object sender, EventArgs e)
            {
                /* The files for this project will reside in a directory we will create.
                 * By default, we will create a directory in a C: drive. If you are planning
                 * to use a different directory, change the value of the following variable. 
                 * In the same way, if you are working on an operating system other than 
                 * Microsoft Windows, make the necessary changes. */
                string strDrive = @"C:\";
                /* This is the main directory where the files of the project will reside.
                 * If necessary, make the appropriate changes. */
                string strPrimaryFolder = strDrive + "Watts A Loan";
    
                // Prepare the directory
                DirectoryInfo diWattsALoan = new DirectoryInfo(strPrimaryFolder);
                // Create the primary directory for this project
                diWattsALoan.Create();
    
                // A Directory for the employees files
                DirectoryInfo diEmployees = diWattsALoan.CreateSubdirectory("Employees");
                // A Directory for the loans contracts files
                diWattsALoan.CreateSubdirectory("Loans Contracts");
                // A Directory for the loans payments files
                diWattsALoan.CreateSubdirectory("Loans Payments");
    
                // Serializing an object
                Employee worker = new Employee()
                {
                    EmployeeNumber = "293-747",
                    FirstName          = "Catherine",
                    LastName           = "Watts",
                    Title              = "Owner - General Manager"
                };
    
                string strEmployee = diEmployees.FullName + @"\" + worker.EmployeeNumber + ".xml";
                XmlSerializer xsEmployee = new XmlSerializer(typeof(Employee));
                TextWriter twEmployee = new StreamWriter(strEmployee);
    
                xsEmployee.Serialize(twEmployee, worker);
                twEmployee.Close();
    
                // Serializing an object
                worker = new Employee()
                {
                    EmployeeNumber = "836-486", FirstName = "Thomas",
                    LastName = "Felton", Title = "Accounts Representative"       
                };
    
                strEmployee = diEmployees.FullName + @"\" + worker.EmployeeNumber + ".xml";
    
                try
                {
                    twEmployee = new StreamWriter(strEmployee);
    
                    xsEmployee.Serialize(twEmployee, worker);
                }
                finally
                {
                    twEmployee.Close();
                }
    
                // Serializing an object
                worker = new Employee()
                {
                    EmployeeNumber = "492-947",
                    FirstName = "Caroline", LastName = "Wernick",
                    Title = "Assistant Manager"         
    
                };
    
                strEmployee = diEmployees.FullName + @"\" + worker.EmployeeNumber + ".xml";
    
                using (twEmployee = new StreamWriter(strEmployee))
                {
                    xsEmployee.Serialize(twEmployee, worker);
                    twEmployee.Close();
                }
    
                // Serializing an object
                worker = new Employee() { EmployeeNumber = "240-750", FirstName = "Catherine",
                                          LastName = "Donato", Title = "Accounts Representative"   };
    
                strEmployee = diEmployees.FullName + @"\" + worker.EmployeeNumber + ".xml";
                xsEmployee = new XmlSerializer(typeof(Employee));
    
                Stream fsEmployee = new FileStream(strEmployee, FileMode.Create, FileAccess.Write, FileShare.Write);
    
                try
                {
                    xsEmployee.Serialize(fsEmployee, worker);
                }
                finally
                {
                    fsEmployee.Close();
                }
    
                // Serializing an object
                worker = new Employee()
                {
                    EmployeeNumber = "804-685",
                    FirstName = "Melissa",
                    LastName = "Browns",
                    Title = "Customer Accounts Representative"
                };
    
                strEmployee = diEmployees.FullName + @"\" + worker.EmployeeNumber + ".xml";
                xsEmployee = new XmlSerializer(typeof(Employee));
    
                using (fsEmployee = new FileStream(strEmployee, FileMode.Create, FileAccess.Write, FileShare.Write))
                {
                    xsEmployee.Serialize(fsEmployee, worker);
                }
    
                // Serializing an object
                worker = new Employee()
                {
                    EmployeeNumber = "429-374",
                    FirstName = "Denise",
                    LastName = "Leighton",
                    Title = "Accounts Manager"
                };
    
                strEmployee = diEmployees.FullName + @"\" + worker.EmployeeNumber + ".xml";
                xsEmployee = new XmlSerializer(typeof(Employee));
                FileInfo fiEmployee = new FileInfo(strEmployee);
                StreamWriter swEmployee = new StreamWriter(fiEmployee.FullName);
    
                xsEmployee.Serialize(swEmployee, worker);
                swEmployee.Close();
            }
        }
    }
  2. To execute the project and save the employees records, on the main menu, click Debug ->Start Without Debugging
  3. Close the form and return to your programming environment
  4. To create a new form, on the main menu, click View -> Add Form (Windows Forms...)
  5. Type Employees as the name of the form
  6. Click Add
  7. Design the form as follows:

    Using the Siblings of an XML Node

    Control (Name) Text Other Properties
    ListView lvwEmployees  
    FullRowSelect: True
    GridLines:     True
    View:          Details
    Anchor:        Top, Bottom, Left, Right
    Button btnClose Close Anchor: Bottom, Right

    List View Columns

    (Name) Text TextAlign Width
    colCounter #   20
    colEmployeeNumber Employee #   90
    colFirstName First Name   80
    colLastName Last Name   80
    colTitle Title   175
  8. Double-click an unoccupied area of the form to generate its Load event
  9. Return to the form and double-click the Close button

Deserializing an Object

Deserialization is the opposite to serialization. It consists of getting an object of collection that is stored in a medium or was sent as a stream. To start, you can create a stream or a text reader and initialize it:

using System.IO;

public class Exercise
{
    void OpenAppliance()
    {
        string fileName = "dischwasher.apl";
        StreamReader srAppliance = new StreamReader(fileName);
    }
}

You must also indicate the type of object you want to deserialize. You can do this by declaring a value of that class. Here is an example:

using System.IO;

public class Dishwasher
{
}

public class Exercise
{
    void OpenAppliance()
    {
        Dishwasher dw = new Dishwasher();

        string fileName = "dischwasher.apl";
        StreamReader srAppliance = new StreamReader(fileName);
    }
}

To deserialize, declare a variable of type XmlSerializer. Remember that this class has many constructors and some of the constructors require that you indicate the type of object you want to work on. Here is an example of declaring and initializing the variable:

using System.IO;
using System.Xml.Serialization;

public class Dishwasher
{
}

public class Program
{
    void OpenAppliance()
    {
        Dishwasher dw = new Dishwasher();
        string fileName = "dischwasher.apl";
        StreamReader srAppliance = new StreamReader(fileName);

        XmlSerializer xs = new XmlSerializer(typeof(Dishwasher));
    }
}

To support deserialization, the XmlSerializer class is equipped with a method named the Deserialize. This method is overloaded with various (seven) versions. One of the versions uses the following syntax:

public object Deserialize(TextReader textReader);

This method takes as argument an object from a class derived from TextReader. This method return a general object object. Therefore, you must cast the returned value to a type of your class. This can be done as follows:

using System.IO;
using System.Xml.Serialization;

public class Dishwasher
{
}

public class Execise
{
    void OpenAppliance()
    {
        Dishwasher dw = new Dishwasher();
        string fileName = "dischwasher.apl";
        StreamReader srAppliance = new StreamReader(fileName);

        XmlSerializer xs = new XmlSerializer(typeof(Dishwasher));

        dw = (Dishwasher)xs.Deserialize(srAppliance);
    }
}

Once you have done this, you have the object and you can use it as you see fit.

Practical LearningPractical Learning: Deserializing Objects

  1. Change the document as follows:
    using System;
    using System.IO;
    using System.Windows.Forms;
    using System.Xml.Serialization;
    
    namespace WattsALoan1
    {
        public partial class Employees : Form
        {
            public Employees()
            {
                InitializeComponent();
            }
    
            private void Employees_Load(object sender, EventArgs e)
            {
                string strEmployees = @"C:\Watts A Loan\Employees";
    
                DirectoryInfo diEmployees = new DirectoryInfo(strEmployees);
                FileInfo[] fiEmployees = diEmployees.GetFiles();
    
                int i = 1;
    
                foreach(FileInfo file in fiEmployees)
                {
                    XmlSerializer xs = new XmlSerializer(typeof(Employee));
    
                    FileStream fsEmployees = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
    
                    Employee empl = (Employee)xs.Deserialize(fsEmployees);
    
                    ListViewItem lviEmployee = new ListViewItem(i.ToString());
    
                    lviEmployee.SubItems.Add(empl.EmployeeNumber);
                    lviEmployee.SubItems.Add(empl.FirstName);
                    lviEmployee.SubItems.Add(empl.LastName);
                    lviEmployee.SubItems.Add(empl.Title);
    
                    lvwEmployees.Items.Add(lviEmployee);
                    i++;
    
                    fsEmployees.Close();
                }
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  2. To create a new class, in the Solution Explorer, right-click WattsALoan1 -> Add Class...
  3. Type Loan as the name of the file and class
  4. Click Add
  5. Change the document as follows:
    namespace WattsALoan1
    {
        public class Loan
        {
            public double LoanAmount     { get; set; }
            public double InterestRate   { get; set; }
            public int    Periods        { get; set; }
            public double InterestAmount { get; set; }
            public double FutureValue    { get; set; }
        }
    }

Serializing and Deserializing a Collection

Seriualizing a collection is as easy as serializing an object. Instead of simply creating an object, create a collection using any of the techniques we have learned or better, use one of the .NET collection classes we we will study in the next few lessons. When creating a XmlSerializer object, pass the type of collection to the constructor. Then call the XmlSerializer.Serialize() method exactly as we learned. The deserialization follows the same steps we reviewed for an object.

Options on Serialization

Serialization and XML Schemas

When you ask the compiler to perform XML serialization, the compiler wants to know the XML schemas that will control the content of the document. Just mentioned in our introduction, you don't need to know anything about XML in order to use XML serialization. In the same way, you don't need to know anything about XML schema to use XML serialization, but it may be a good idea to know what an XML document looks like and to know what an XML schema is (which is why we first studied XML and schemas in previous lessons).

When performing XML serialization, if you don't provide an XML schema, the compiler will use one of the default schemas that come with Microsoft Visual Studio. Otherwise, if you want to provide your own schema or a specific schema from Microsoft Visual Studio, the XmlSerializer class is equipped with various constructors that allow you to provide that information.

A Property of a Class/Structure Type

We already know how to create a property whose type is a class or structure type. When the class is serialized, the compiler will create a node whose name is the name of the property. The properties of the of the other class or structure would be created as child nodes.

Serializing a Tuple

After creating a tuple, to serialize it, for the argument of the typeof() operator, pass the formula of the tuple. Everything else follows the same steps as for an object. Here is an example:

using System.IO;
using System.Xml.Serialization;

namespace GeneralSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            (long number, string first, string last, double salary) contractor = (297492, "Patrick", "Landsford", 48860);

            XmlSerializer xsHumanResources = new XmlSerializer(typeof((long, string, string, double)));
            TextWriter twContractor = new StreamWriter(@"C:\Exercises\Contractor.ctr");

            try
            {
                xsHumanResources.Serialize(twContractor, contractor);
            }
            finally
            {
                twContractor.Close();
            }
        }
    }
}

In the same way, you can create a property of a tuple class in a class. When you serialize, the ccmpiler will create a node that uses the name of the property. Each of the items of the tuple will be a child node.

Practical LearningPractical Learning: Serializing an Object

  1. To create a new class, on the main menu, click Project -> Add Class...
  2. Type CustomerAccount as the name of the class
  3. Click Add
  4. Change the document as follows:
    using System;
    
    namespace WattsALoan1
    {
        public class CustomerAccount
        {
            public int      LoanNumber       { get; set; }
            public string   ProcessedBy      { get; set; }
            public DateTime DateAllocated    { get; set; }
            public (string FirstName, string LastName, string PhoneNumber) Customer { get; set; }
            public string   LoanType         { get; set; }
            public Loan     Finance          { get; set; }
            public double   MonthlyPayment   { get; set; }
            public DateTime PaymentStartDate { get; set; }
            public double   CurrentBalance   { get; set; }
        }
    }
  5. To add a new class, in the Solution Explorer, right-click WattsALoan1 -> Add -> Class...
  6. Type Payment as the name of the file
  7. Click Add
  8. Change the document as follows:
    using System;
    
    namespace WattsALoan1
    {
        public class Payment
        {
            public int      PaymentNumber { get; set; }
            public DateTime PaymentDate   { get; set; }
            public string   ProcessedBy   { get; set; }
            public int      LoanNumber    { get; set; }
            public double   AmountPaid    { get; set; }
        }
    }
  9. To create a new form, in the Solution Explorer, right-click WattsALoan -> Add Form (Windows Forms)...
  10. Type LoanPreparation as the name of the file and form
  11. Press Enter
  12. Design the form as follows:

    Options on Serialization

    Control (Name) Text Other Properties
    Label   Loan Number:  
    TextBox txtLoanNumber    
    GroupBox   Loan Processed By  
    Label   Employee #:  
    TextBox txtEmployeeNumber    
    TextBox txtEmployeeName    
    GroupBox   Customer Information  
    Label   First Name:  
    TextBox txtFirstName    
    Label   Last Name:  
    TextBox txtLastName    
    Label   Phone #:  
    MaskedTextBox mtbPhoneNumber   Mask: Phone Number
    Label   Date Allocated:  
    GroupBox   Fincancial Details  
    Label   Loan Type:  
    ComboBox cbxLoansTypes   Items:
    Other
    Personal Loan
    Car Financing
    Boat Financing
    Furniture Purchase
    Musical Instrument
    Label   Interest Rate:  
    TextBox txtInterestRate   TextAlign: Right
    Label   %  
    Label   Loan Amount:  
    TextBox txtLoanAmount   TextAlign: Right
    Label   Periods:  
    TextBox txtPeriods   TextAlign: Right
    Label   mois  
    Label   ________________  
    Label   Interest Amount:  
    TextBox txtInterestAmount   TextAlign: Right
    Label   Future Value:  
    TextBox txtFutureValue   TextAlign: Right
    Label   ______________  
    Label   Monthly Payment:  
    TextBox txtMonthlyPayment   TextAlign: Right
    Label   Payment Start Date:  
    DateTimePicker dtpPaymentStartDate    
    Label   Previous Balance:  
    TextBox txtPreviousBalance   TextAlign: Right
    Label   Current Balance:  
    TextBox txtCurrentBalance   TextAlign: Right
    Button btnSaveLoanRecord Save Loan Record  
    Button btnClose Close  
  13. In the form, click the Employee # text box
  14. In the Properties window, click the Events button Events
  15. Double-click Leave
  16. Return to the form and double-click the Save Loan Record button
  17. Return to the form and double-click the Close button
  18. Change some values as follows:
    using System;
    using System.IO;
    using System.Windows.Forms;
    using System.Xml.Serialization;
    
    namespace WattsALoan11
    {
        public partial class LoanPreparation : Form
        {
            public LoanPreparation()
            {
                InitializeComponent();
            }
    
            private void txtEmployeeNumber_Leave(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtEmployeeNumber.Text))
                    return;
    
                string strEmployees = @"C:\Watts A Loan-1\Employees";
    
                DirectoryInfo diEmployees = new DirectoryInfo(strEmployees);
                FileInfo[] fiEmployees = diEmployees.GetFiles();
    
                int i = 1;
    
                foreach (FileInfo file in fiEmployees)
                {
                    if( file.Name.Substring(0, 7) == txtEmployeeNumber.Text)
                    {
                        XmlSerializer xs = new XmlSerializer(typeof(Employee));
                        
                        FileStream fsEmployees = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
                        
                        Employee empl = (Employee)xs.Deserialize(fsEmployees);
    
                        txtEmployeeName.Text = empl.LastName + ", " + empl.FirstName;
                        
                        fsEmployees.Close();
    
                        return;
                    }
                    else
                        txtEmployeeName.Text = " ";
                }
            }
    
            private void btnSaveLoanRecord_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtLoanNumber.Text))
                {
                    MessageBox.Show("You must provide a natural number as the loan identifier.", "Watts' A Loan");
                    return;
                }
    
                if (string.IsNullOrEmpty(txtEmployeeNumber.Text))
                {
                    MessageBox.Show("You must enter the employee number of the staff member " + 
                                    "who processed (and probably approved) the loan.", "Watts' A Loan");
                    return;
                }
    
                TextWriter twLoan = null;
    
                try
                {
                    string strLoan = @"C:\Watts A Loan-1\Loans Contracts\" + txtLoanNumber.Text + ".xml";
                    Loan loan = new Loan();
    
                    loan.LoanAmount = double.Parse(txtLoanAmount.Text);
                    loan.InterestRate = double.Parse(txtInterestRate.Text);
                    loan.Periods = int.Parse(txtPeriods.Text);
                    loan.InterestAmount = double.Parse(txtInterestAmount.Text);
                    loan.FutureValue = double.Parse(txtFutureValue.Text);
                    loan.MonthlyPayment = double.Parse(txtMonthlyPayment.Text);
    
                    CustomerAccount account = new CustomerAccount();
    
                    account.LoanNumber = int.Parse(txtLoanNumber.Text);
                    account.ProcessedBy = txtEmployeeNumber.Text;
                    account.DateAllocated = dtpDateAllocated.Value;
                    account.Customer = (txtFirstName.Text, txtLastName.Text, mtbPhoneNumber.Text);
                    account.LoanType = cbxLoansTypes.Text;
                    account.Finance = loan;
                    account.PaymentStartDate = dtpPaymentStartDate.Value;
                    account.CurrentBalance = double.Parse(txtCurrentBalance.Text);
    
                    XmlSerializer xsLoan = new XmlSerializer(typeof(CustomerAccount));
                    twLoan = new StreamWriter(strLoan);
    
                    xsLoan.Serialize(twLoan, account);
                }
                finally
                {
                    twLoan.Close();
                }
    
                Close();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  19. To create a new form, on the main menu, click Project -> Add Form (Windows Forms)...
  20. Type LoanEditor
  21. Press Enter
  22. Display the Loan Preparation form. Press Ctrl + A to select everything on it. Press Ctrl + C to copy
  23. Display the Loan Editor form
  24. Add a button with the following characteristics:
    (Name) btnOpen
    Text: Open
    
    

    Serializing an Object

  25. On the form, double-click the Open button
  26. Change the document as follows:
    using System;
    using System.IO;
    using System.Windows.Forms;
    using System.Xml.Serialization;
    
    namespace WattsALoan11
    {
        public partial class LoanEditor : Form
        {
            public LoanEditor()
            {
                InitializeComponent();
            }
    
            private void btnOpen_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtLoanNumber.Text))
                    return;
    
                string strEmployees = @"C:\Watts A Loan-1\Employees";
                string strContracts = @"C:\Watts A Loan-1\Loans Contracts";
    
                DirectoryInfo diContracts = new DirectoryInfo(strContracts);
                FileInfo[] fiContracts = diContracts.GetFiles();
    
                foreach (FileInfo file in fiContracts)
                {
                    if (file.Name.Substring(0, 6) == txtLoanNumber.Text)
                    {
                        using (FileStream fsContracts = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            XmlSerializer xsContracts = new XmlSerializer(typeof(CustomerAccount));
    
                            CustomerAccount contract = (CustomerAccount)xsContracts.Deserialize(fsContracts);
    
                            txtEmployeeNumber.Text = contract.ProcessedBy;
                            dtpDateAllocated.Value = contract.DateAllocated;
                            txtFirstName.Text = contract.Customer.FirstName;
                            txtLastName.Text = contract.Customer.LastName;
                            mtbPhoneNumber.Text = contract.Customer.PhoneNumber;
                            cbxLoansTypes.Text = contract.LoanType;
                            txtLoanAmount.Text = contract.Finance.LoanAmount.ToString("F");
                            txtInterestRate.Text = contract.Finance.InterestRate.ToString("F");
                            txtPeriods.Text = contract.Finance.Periods.ToString("F");
                            txtInterestAmount.Text = contract.Finance.InterestAmount.ToString("F");
                            txtFutureValue.Text = contract.Finance.FutureValue.ToString("F");
                            txtMonthlyPayment.Text = contract.Finance.MonthlyPayment.ToString("F");
                            dtpPaymentStartDate.Value = contract.PaymentStartDate;
                            txtCurrentBalance.Text = txtPreviousBalance.Text = contract.CurrentBalance.ToString("F");
                        }
                    }
                }
    
                DirectoryInfo diEmployees = new DirectoryInfo(strEmployees);
                FileInfo[] fiEmployees = diEmployees.GetFiles();
    
                foreach (FileInfo file in fiEmployees)
                {
                    if (file.Name.Substring(0, 7) == txtEmployeeNumber.Text)
                    {
                        XmlSerializer xs = new XmlSerializer(typeof(Employee));
    
                        FileStream fsEmployees = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
    
                        Employee empl = (Employee)xs.Deserialize(fsEmployees);
    
                        txtEmployeeName.Text = empl.LastName + ", " + empl.FirstName;
    
                        fsEmployees.Close();
    
                        return;
                    }
                }
            }
        }
    }
  27. In the Solution Explorer, double-click WattsALoan.cs to display the form
  28. Design the form as follows:

    Modeling a Picnic Table

    Control (Name) Text
    Button btnLoanPreparation Loan Preparation...
    Button btnLoanEditon Loan Editor...
    Button btnEmployees Employees...
    Button btnClose Close
  29. On the form, double-click the Loan Preparation button
  30. Return to the form and double-click the Loan Editor button
  31. Return to the form and double-click the Employees button
  32. Return to the form and double-click the Close button
  33. Change the document as follows:
    using System;
    using System.Windows.Forms;
    
    namespace WattsALoan11
    {
        public partial class WattsALoan : Form
        {
            public WattsALoan()
            {
                InitializeComponent();
            }
    
            private void WattsALoan_Load(object sender, EventArgs e)
            {
                
            }
    
            private void btnLoanPreparation_Click(object sender, EventArgs e)
            {
                LoanPreparation lp = new LoanPreparation();
    
                lp.ShowDialog();
            }
    
            private void btnLoanEditor_Click(object sender, EventArgs e)
            {
                LoanEditor le = new LoanEditor();
    
                le.ShowDialog();
            }
    
            private void btnEmployees_Click(object sender, EventArgs e)
            {
                Employees staff = new Employees();
    
                staff.ShowDialog();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  34. To execute the application, on the main menu, click Debug -> Start Without Debugging:
  35. Click the Loan Preparation button
  36. Enter the following values:
    Loan Number:        100001
    Employee #:         429-374
    First Name:         Joanne
    Last Name:          Kennan
    Phone Number:       3011824957
    Date Allocated:     January 18, 2021
    Loan Type:          Personal Loan
    Interest Rate:      14.65
    Loan Amount:        2500
    Periods:            36
    Interest Amount:    1098.92
    Future Value:       3598.92
    Monthly Payment:    99.97
    Payment Start Date: March 1st, 2021
    Previous Balance:   3598.92
    Current Balance:    3598.92
  37. Click the Save Loan Record button
  38. Click the Loan Preparation button
  39. Enter the following values:
    Loan Number:        100002
    Employee #:         492-947
    First Name:         Stephen
    Last Name:          Haller
    Phone Number:       2401668369
    Date Allocated:     February 22, 2021
    Loan Type:          Boat Financing
    Interest Rate:      12.25
    Loan Amount:        16500
    Periods:            60
    Interest Amount:    $10,106.40 
    Future Value:       26,606.40
    Monthly Payment:    443.44
    Payment Start Date: March 1st, 2021
    Previous Balance:   26,606.40
    Current Balance:    26,606.40
  40. Click the Save Loan Record button
  41. Click the Loan Record button
  42. In the Loan Number text box, type 100002
  43. Click the Open button
  44. Close the forms and return to Microsoft Visual Studio
  45. Close your programming environment

Previous Copyright © 2001-2021, C# Key Next