14

I have a main class called theGarage, which contains instances of our customer, supplier, and jobs classes.

I want to save the program data to an XML file, I have used the code below (just a snippet, I have matching code for the other classes). I am wondering if there is an easier way for me to do this, like write the whole theGarage class to an XML file and read it in without having to write all this code like I have below.

   public void saveToFile()
    {
        using (XmlWriter writer = XmlWriter.Create("theGarage.xml"))
        {
            writer.WriteStartDocument();

            ///
            writer.WriteStartElement("theGarage");
            writer.WriteStartElement("Customers");

            foreach (Customer Customer in Program.theGarage.Customers)
            {
                writer.WriteStartElement("Customer");
                writer.WriteElementString("FirstName", Customer.FirstName);
                writer.WriteElementString("LastName", Customer.LastName);
                writer.WriteElementString("Address1", Customer.Address1);
                writer.WriteElementString("Address2", Customer.Address2);
                writer.WriteElementString("Town", Customer.Town);
                writer.WriteElementString("County", Customer.County);
                writer.WriteElementString("PostCode", Customer.Postcode);
                writer.WriteElementString("TelephoneHome", Customer.TelephoneHome);
                writer.WriteElementString("TelephoneMob", Customer.TelephoneMob);

                //begin vehicle list
                writer.WriteStartElement("Vehicles");

                foreach (Vehicle Vehicle in Customer.Cars)
                {
                    writer.WriteStartElement("Vehicle");
                    writer.WriteElementString("Make", Vehicle.Make);
                    writer.WriteElementString("Model", Vehicle.Model);
                    writer.WriteElementString("Colour", Vehicle.Colour);
                    writer.WriteElementString("EngineSize", Vehicle.EngineSize);
                    writer.WriteElementString("Registration", Vehicle.Registration);
                    writer.WriteElementString("Year", Vehicle.YearOfFirstReg);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
        }
    }
dav_i
  • 27,509
  • 17
  • 104
  • 136
developer__c
  • 636
  • 3
  • 11
  • 31
  • what kind of application are you writing? Are you just trying to save a session across uses for a single-user, GUI application? Otherwise (if you're doing something that could be used by multiple concurrent users, for instance) you may want to consider not storing the info in files. Even in the single user scenario, there may be better alternatives (like SQLite) to store your data – Paolo Falabella Nov 07 '12 at 10:35
  • if we had the resources the choice would be that the program will connected to a MySQL database - thats the method I am more familiar programming with. – developer__c Nov 07 '12 at 14:16
  • well, there are various "lighter" options depending on your scenario. If you can expand some more on what kind of application you're writing people here will be able to suggest something suitable. – Paolo Falabella Nov 07 '12 at 15:16

4 Answers4

47

There is much simpler way of serializing objects, use XmlSerializer instead. See documentation here.

Code snippet to serialize your garage to file could look like:

var garage = new theGarage();

// TODO init your garage..

XmlSerializer xs = new XmlSerializer(typeof(theGarage));
TextWriter tw = new StreamWriter(@"c:\temp\garage.xml");
xs.Serialize(tw, garage);

And code to load garage from file:

using(var sr = new StreamReader(@"c:\temp\garage.xml"))
{
   garage = (theGarage)xs.Deserialize(sr);
}
Michal Klouda
  • 14,263
  • 7
  • 53
  • 77
7

What about a couple of nifty extension methods, then you can easily read/write this to/from file.

public static class Extensions
{
    public static string ToXml(this object obj)
    {
        XmlSerializer s = new XmlSerializer(obj.GetType());
        using (StringWriter writer = new StringWriter())
        {
            s.Serialize(writer, obj);
            return writer.ToString();
        }
    }

    public static T FromXml<T>(this string data)
    {
        XmlSerializer s = new XmlSerializer(typeof(T));
        using (StringReader reader = new StringReader(data))
        {
            object obj = s.Deserialize(reader);
            return (T)obj;
        }
    }
}

example

 var xmlData = myObject.ToXml();

 var anotherObject = xmlData.FromXml<ObjectType>();
Richard Friend
  • 15,800
  • 1
  • 42
  • 60
2

I just wrote a blog post on saving an object's data to Binary, XML, or Json. Here is the functions to write and read the class instance to/from XML. See my blog post for more details.

Requires the System.Xml assembly to be included in your project.

/// <summary>
/// Writes the given object instance to an XML file.
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
    TextWriter writer = null;
    try
    {
        var serializer = new XmlSerializer(typeof(T));
        writer = new StreamWriter(filePath, append);
        serializer.Serialize(writer, objectToWrite);
    }
    finally
    {
        if (writer != null)
            writer.Close();
    }
}

/// <summary>
/// Reads an object instance from an XML file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the XML file.</returns>
public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
    TextReader reader = null;
    try
    {
        var serializer = new XmlSerializer(typeof(T));
        reader = new StreamReader(filePath);
        return (T)serializer.Deserialize(reader);
    }
    finally
    {
        if (reader != null)
            reader.Close();
    }
}

Example

// Write the list of salesman objects to file.
WriteToXmlFile<Customer>("C:\TheGarage.txt", customer);

// Read the list of salesman objects from the file back into a variable.
Customer customer = ReadFromXmlFile<Customer>("C:\TheGarage.txt");
deadlydog
  • 22,611
  • 14
  • 112
  • 118
0

For my project I use DataContractSerializer. I contrast to XmlSerializer it can handle multiple references to the same object in such a manner that data is not duplicated in xml and restored as saved.

Rafal
  • 12,391
  • 32
  • 54