Eric
Eric

Reputation: 2128

Name Each Element in Array

I have an array whose indices map back to Enum values. I would like to use the C# Xml Serialization libraries to serialize this array. However, I would like each Xml node to say the name of the Enum type that it represents. How can I do this?

Example:

public class NumberOfEmployees
{
   public enum EmployeeType { Lawyer, Doctor, Engineer };

   public int[] NumEmployees { get; set; }

   // Constructor initializes array to size of "EmployeeType"
   public NumberOfEmployees()
   {
      int size = Enum.GetValues(typeof(EmployeeType)).Length;
      this.NumEmployees = new int[size];
   }    
}


Main()
{
   NumberOfEmployees numEmployees = new NumberOfEmployees();
   // Add doctors, lawyers, engineers, etc...
   // numEmployees.NumEmployees[(int)NumberOfEmployees.Lawyer] = 3;
   // numEmployees.NumEmployees[(int)NumberOfEmployees.Doctor] = 2;
   // numEmployees.NumEmployees[(int)NumberOfEmployees.Engineer] = 1;

   // Serialize to "file"
   FileStream fs = new FileStream(file, FileMode.OpenOrCreate);
   XmlSerializer xml = new XmlSerializer(typeof(NumberOfEmployees));   
   xml.Serialize(fs, numEmployees);
   fs.Close();
}

The end result is xml that looks something like this:

<NumEmployees>
  <int>3</int>
  <int>2</int>
  <int>1</int>
</NumEmployees>

But what I want is:

<NumEmployees>
  <Lawyer>3</Lawyer>
  <Doctor>2</Doctor>
  <Engineer>1</Engineer>
</NumEmployees>

I can not store each number separately -- it must be an array.

Thanks.

Upvotes: 1

Views: 459

Answers (1)

luksan
luksan

Reputation: 7757

You can implement the IXmlSerializable interface to completely customize serialization with XmlSerializer. Something similar to the following:

public class NumberOfEmployees : IXmlSerializable
{
    public int[] NumEmployees { get; set; }

    // Constructor initializes array to size of "EmployeeType"
    public NumberOfEmployees()
    {
        int size = Enum.GetValues(typeof(EmployeeType)).Length;
        this.NumEmployees = new int[size];
    }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        reader.ReadStartElement();
        NumEmployees[(int)EmployeeType.Lawyer] = int.Parse(reader.ReadElementString("Lawyer"));
        NumEmployees[(int)EmployeeType.Doctor] = int.Parse(reader.ReadElementString("Doctor"));
        NumEmployees[(int)EmployeeType.Engineer] = int.Parse(reader.ReadElementString("Engineer"));
        reader.ReadEndElement();
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString("Lawyer", NumEmployees[(int)EmployeeType.Lawyer].ToString());
        writer.WriteElementString("Doctor", NumEmployees[(int)EmployeeType.Doctor].ToString());
        writer.WriteElementString("Engineer", NumEmployees[(int)EmployeeType.Engineer].ToString());
    }
}

After you've done all that it might seem pointless to still use XmlSerializer since your class is handling all the work of serialization. It still makes sense, however, if the NumberOfEmployees is part of a larger XML structure (which I assume it is).

Also note that the code doesn't do any validation, because this is a simple example. So all three array elements will be expected to exist when the class is serialized, and all three XML elements will be expected to exist when it is deserialized.

More info on the IXmlSerializable interface is available here:

http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

Upvotes: 4

Related Questions