Two Tales of Debugging ApplicationSettingsBase

[3 minute read]

One: The Constructor

Let’s say we have the following class that inherits from ApplicationSettingsBase:

public class MySettings : ApplicationSettingsBase
{
	[UserScopedSetting]
	public List<SomeType> ListOfSomeType
	{
		get { return (List<SomeType>)this["ListOfSomeType"]; }
		set { this["ListOfSomeType"] = value; }
	}
}

Where SomeType is defined as:

public class SomeType
{
    public SomeType(string someString, int someInt)
    {
      this.SomeString = someString;
		  this.SomeInt = someInt;
    }

    public string SomeString { get; set; }
    public int SomeInt { get; set; }
}

And we run the following code:

MySettings settings = new MySettings();
settings.ListOfSomeType = new List<SomeType>()
{
  new SomeType("hello!", 102),
  new SomeType("bye!", 442)
};

settings.Save();

What do we get? Nada:

Nada

Turns out you have to supply a parameterless constructor in order for serialization to work. When SomeType looks like this:

public class SomeType
{
  public SomeType() { }

	public SomeType(string someString, int someInt)
	{
		this.SomeString = someString;
		this.SomeInt = someInt;
	}

    public string SomeString { get; set; }
    public int SomeInt { get; set; }
}

This is the xml output after running the same code snippet from above:

NotNada

Seems to make sense in retrospect. I’m by no means an expert in serialization, but my guess is that deserialization wouldn’t be possible without a parameterless constructor because the stored property values cannot be correlated with constructor parameters. Thanks again, Captain Hindsight!

Property Accessors

Now let’s say we decide that SomeType’s SomeString property should have a private set accessor. SomeType then looks like this:

public class SomeType
{
    public SomeType() { }

    public SomeType(string someString, int someInt)
    {
        this.SomeString = someString;
        this.SomeInt = someInt;
    }

    public string SomeString { get; private set; }
    public int SomeInt { get; set; }
}

Kinda dumb in a way, because (again) how can the object be deserialized if one of the properties has a private set accessor? Well, let’s assume (1) a private set makes sense outside the context of serialization and (2) that the value of SomeString doesn’t need to be stored. I encountered that exact situation today. In a fairly large class which is being stored via a List property of a ApplicationSettingsBase class (much like SomeType and MySettings above), I had added a boolean property with a private accessor without realizing that I effectively broke the serialization process. Quite a bit of time had passed before a user pointed out a problem and it took me several hours to connect the dots and see what was going wrong. The fix, however, was as simple as they come. Since the property in question does not need its value stored, decorating it with the XmlIgnoreAttribute solves the problem. Going back to the SomeType example, if it’s modified like this…

public class SomeType
{
    public SomeType() { }

    public SomeType(string someString, int someInt)
    {
        this.SomeString = someString;
        this.SomeInt = someInt;
    }

    [XmlIgnore]
    public string SomeString { get; private set; }
    public int SomeInt { get; set; }
}

…serialization will work correctly and only SomeInt will be stored. Too bad checking for private accessors was nowhere near the top of my debugging checklist today.