1

I want to make it easy to store lot of data into a XML file. Before I did it with structures and that worked well, but now I want to make use of classes, see my example below. when saving to XML, the subclasses are not saved to the XML.

In the XML file I see a bunch of

<logic>
<logicData xsi:nil="true" />
<logicData xsi:nil="true" />
<logicData xsi:nil="true" />

This is my current code that I use

  public class colorProfileSettings
{
    public int[] btn_background = new int[16];
    public int[] btn_input = new int[16];
    public int[] btn_press = new int[16];
}

public class logicData
{
    public colorProfileSettings[] colors = new colorProfileSettings[2];
    public int configBtnLedTest = 0;
    public int configBtnDimPlus = 0;
    public int configBtnDimMin = 0;
    public int configBtnCleaning = 0;
    public int configBtnDayNightToggle = 0;
    public int groupBg = 0;
    public int groupLedTest = 0;
    public int groupDimming = 10;
}

public class ClassConfigData
{
    public logicData[] logic = new logicData[100];
    public string fileLocName;
}

public ClassConfigData data = new ClassConfigData();

public void WriteXML(string fileLoc)
{
    try
    {
        if (System.IO.File.Exists(fileLoc))
        {
            XmlSerializer writer = new XmlSerializer(typeof(ClassConfigData));
            StreamWriter file = new StreamWriter(@fileLoc);
            writer.Serialize(file, data);
            file.Close();
        }
        else
        {
            throw new ArgumentNullException("Not a valid file selected.");
        }
    }
    catch (Exception e)
    {
        throw e;
    }
}
user1439564
  • 105
  • 1
  • 2
  • 8
  • possible duplicate of [How to save/restore serializable object to/from file?](http://stackoverflow.com/questions/6115721/how-to-save-restore-serializable-object-to-from-file) – DanielS May 18 '15 at 19:12
  • Well what did you expect? You made an array of `100` empty elements. – Der Kommissar May 18 '15 at 19:12
  • Add `public ClassConfigData() { for (int i = 0; i < logic.Length; i++) { logic[i] = new logicData(); } }` inside `class ClassConfigData` and you'll see **very** different results. – Der Kommissar May 18 '15 at 19:14
  • You mention "subclasses", but there's not any sort of inheritance going on. Is there more to what you're asking? – Colin May 18 '15 at 19:16

1 Answers1

1

The problem is that you never instantiate any of the logicData array elements.

I changed your ClassConfigData class to the following, and your logicData class to the following, and it worked as expected.

public class ClassConfigData
{
    public logicData[] logic = new logicData[100];
    public string fileLocName;

    public ClassConfigData()
    {
        for (int i = 0; i < logic.Length; i++)
        {
            logic[i] = new logicData();
        }
    }
}

public class logicData
{
    public colorProfileSettings[] colors = new colorProfileSettings[2];
    public int configBtnLedTest = 0;
    public int configBtnDimPlus = 0;
    public int configBtnDimMin = 0;
    public int configBtnCleaning = 0;
    public int configBtnDayNightToggle = 0;
    public int groupBg = 0;
    public int groupLedTest = 0;
    public int groupDimming = 10;

    public logicData()
    {
        for (int i = 0; i < colors.Length; i++)
        {
            colors[i] = new colorProfileSettings();
        }
    }
}

Then I ran WriteXML("test.xml"); and it did exactly what it should have.

<?xml version="1.0" encoding="utf-8"?>
<ClassConfigData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <logic>
    <logicData>
      <colors>
        <colorProfileSettings>
          <btn_background>
            <int>0</int>
            ...
          </btn_background>
          ...
        </colorProfileSettings>
        ...
      </colors>
      <configBtnLedTest>0</configBtnLedTest>
      <configBtnDimPlus>0</configBtnDimPlus>
      <configBtnDimMin>0</configBtnDimMin>
      <configBtnCleaning>0</configBtnCleaning>
      <configBtnDayNightToggle>0</configBtnDayNightToggle>
      <groupBg>0</groupBg>
      <groupLedTest>0</groupLedTest>
      <groupDimming>10</groupDimming>
    </logicData>
    <logicData>
      <colors>
        <colorProfileSettings>
          <btn_background>
            <int>0</int>
            ...
          </btn_background>
          ...
        </colorProfileSettings>
        ...
      </colors>
      <configBtnLedTest>0</configBtnLedTest>
      <configBtnDimPlus>0</configBtnDimPlus>
      <configBtnDimMin>0</configBtnDimMin>
      <configBtnCleaning>0</configBtnCleaning>
      <configBtnDayNightToggle>0</configBtnDayNightToggle>
      <groupBg>0</groupBg>
      <groupLedTest>0</groupLedTest>
      <groupDimming>10</groupDimming>
    </logicData>
    ...

Also, anytime you create an array of a reference type (a class), then you must instance each element of the array. Otherwise, they are all null, and as such when serialized there will be no sub-properties, as they do not exist yet! The reason you did not have to do this with structs is because each time you create an array of structure types (which are value types), the CLR clears the memory of the array to new instances of the struct type for each element. This is also why in a struct you must specify a value for every property when you create a constructor in a structure.

The following code demonstrates this fact:

public struct StructureType
{
    public int number;
    public int otherNumber;
}

public class ClassType
{
    public int number;
    public int otherNumber;
}

StructureType[] s1 = new StructureType[2];
s1[0].number = 25;
ClassType[] c1 = new ClassType[2];
c1[0].number = 25;

You will get a NullReferenceException on the c1[0].number = 25; line, as c1[0] does not exist. But s1[0].number = 25; works as s1[0] is defaulted to all zero's in memory.

Der Kommissar
  • 5,848
  • 1
  • 29
  • 43