2

In the code that I'm working on, there are some properties that are serialized. All of them works fine as far as I can see, but one. Here's the code:

    // Fields that the properties use.
    private bool _useAlertColors = false;
    private List<Int32> _colorArgb = new List<Int32>(new Int32[]{Color.White.ToArgb(), Color.Yellow.ToArgb(), Color.Red.ToArgb()});

    // The one that does not work.
    public List<Color> AlertColors
    {
        get
        {
            List<Color> alertColors = new List<Color>();

            foreach (Int32 colorValue in _colorArgb)
            {
                alertColors.Add(Color.FromArgb(colorValue));
            }

            return alertColors;
        }

        set
        {
            // If there's any difference in colors
            // then add the new color
            for (int i = 0; i < _colorArgb.Count; i++)
            {
                if (_colorArgb[i] != value[i].ToArgb())
                {
                    _colorArgb[i] = value[i].ToArgb();
                    HasChanged = true;
                }

            }
        }
    }

    // One of those that work.
    public bool UseAlertColors
    {
        get
        {
            return _useAlertColors;
        }

        set
        {
            if (_useAlertColors != value)
            {
                _useAlertColors = value;
                HasChanged = true;
            }
        }
    }

    // Serializing method.
    public bool Serialize(string filePath)
    {
        if (string.IsNullOrEmpty(filePath))
        {
            Logger.Log("Can't save settings, empty or null file path.");

            return false;
        }

        FileStream fileStream = null;

        try
        {
            fileStream = new FileStream(filePath, FileMode.Create);
            FilePath = filePath;
            System.Xml.Serialization.XmlSerializerFactory xmlSerializerFactory =
                new XmlSerializerFactory();
            System.Xml.Serialization.XmlSerializer xmlSerializer =
                xmlSerializerFactory.CreateSerializer(typeof(Settings));

            xmlSerializer.Serialize(fileStream, this);

            Logger.Log("Settings have been saved successfully to the file " + filePath);
        }
        catch (ArgumentException argumentException)
        {
            Logger.Log("Error while saving the settings. " + argumentException.Message);

            return false;
        }
        catch (IOException iOException)
        {
            Logger.Log("Error while saving the settings. " + iOException.Message);

            return false;
        }
        finally
        {
            if (fileStream != null)
                fileStream.Close();
        }

        return true;
    }

After the serialization, this is what I end up with:

  <UseAlertColors>true</UseAlertColors>
  <AlertColors>
    <Color />
    <Color />
    <Color />
  </AlertColors>

What is wrong with the AlertColors property? Why is it not serialized?

Edit: I've changed the AlertColors property accordingly and it still is not working:

    public List<int> AlertColors
    {
        get
        {
            return _colorArgb;
        }

        set
        {
            // If there's any difference in colors
            // then add the new color
            for (int i = 0; i < _colorArgb.Count; i++)
            {
                if (_colorArgb[i] != value[i])
                {
                    _colorArgb[i] = value[i];
                    HasChanged = true;
                }

            }
        }
    }

What I get in the .xml file is this:

  <AlertColors>
    <int>-1</int>
    <int>-8355840</int>
    <int>-65536</int>
  </AlertColors>

Which are the very first values that were set when the _colorArgb field was initialized. I can see the field change during the program execution, but when the covering property is serialized, it is serialized with the initial value of the underlying field.

What is causing the problem?

hattenn
  • 4,371
  • 9
  • 41
  • 80

1 Answers1

4

XMLSerializer only uses public properties of a class when serializing - The Color Class has none.

Heres a good example of how to get around it: http://www.codeproject.com/Articles/2309/NET-XML-Serialization-a-settings-class

Chris
  • 2,471
  • 25
  • 36
  • 1
    Minor point: it also serializes public fields, but that doesn't change anything important here. You're entirely right that `Color` is not friendly with `XmlSerializer` – Marc Gravell Oct 24 '12 at 07:54
  • I changed the code but it is still not working. I've denoted the changes in the question. – hattenn Oct 24 '12 at 08:20
  • use a DataContractSerializer instead. – Jaster Oct 24 '12 at 08:21
  • But what is wrong with this code? There are `int` properties and they are serialized. – hattenn Oct 24 '12 at 08:22
  • its working perfectly - you've changed it from Color to int and now it serializes an int - I'm confused as to what you're asking for. – Chris Oct 24 '12 at 08:25
  • It doesn't serialize the `int`. It just serializes the initial value of the `_colorArgb` field. I change the property with different colors, but it reverts it back to the initial value when serializing. – hattenn Oct 24 '12 at 08:31
  • where are you setting the new colour? can you show that part? if you're doing something like this: AlertColors[2] = Color.AntiqueWhite; then you wont be calling the setter again. – Chris Oct 24 '12 at 08:55
  • This is how it is set `AlertColors = someOtherColorList;`. – hattenn Oct 24 '12 at 08:59
  • I've just realized that, the problem is not the serialization process, but the deserialization. I'm looking into it at the moment. I'd really appreciate if you have any insights. – hattenn Oct 24 '12 at 09:10
  • For some reason, when it is deserializing, it is appending the colors from the xml file to the `_colorArgb` list. The list ends up with the three inital colors, plus the three colors that are read from the xml file. – hattenn Oct 24 '12 at 09:18
  • I have asked that as a separate question here: http://stackoverflow.com/questions/13046474/xml-deserialization-appends-to-list – hattenn Oct 24 '12 at 09:34
  • debug and put a breakpoint here: foreach (Int32 colorValue in _colorArgb) { alertColors.Add(Color.FromArgb(colorValue)); } watch it cycle through there. – Chris Oct 24 '12 at 09:35