When trying to write reliable, maintainable software, it’s important to try and minimize duplication. When you find yourself writing the same magic number in multiple places, you move it into a named constant to eliminate the duplication. When you find yourself writing the same expression multiple times, you move it into a named function, or perhaps a property. Sometimes, you find yourself dealing with higher level duplication – entire concepts and patterns that you find yourself writing again and again. Many modern languages provide tools to help you eliminate this kind of duplication: class inheritance allows you to share common logic between classes by inheriting that logic from a parent class, and generic types allow you to apply a generic pattern to multiple individual types. Both of these tools work with the aid of the compiler, so they interact well with debugging tools and allow you to catch most errors at compile time. Sometimes, though, you run into duplication that can’t easily be eliminated, even with the aid of the compiler.

In many graphical applications, a common pattern is the need to remember user preferences or inputs. Modern languages provide useful tools that can make this task simpler – for example, both Java and C# provide ways to automatically serialize an entire data structure into XML, which eliminates the need to manually read/write your preference values. Unfortunately, even with the aid of these features, you still find yourself with a lot of duplication – even if the runtime can automatically serialize your data structure, you still have to fill the structure out with your preferences, or read them back in manually. I’m going to demonstrate how you can use a little-known aspect of the new LINQ feature in C# 3.5 to eliminate duplication with the aid of the compiler.

As an example, we’ll be using the simple application shown above. It’s a Windows Forms dialog box, with a few different controls, set up to remember user inputs between sessions. You can download the source code for this application below:

Preferences Example (v1)

If you run the application, input some values, and click OK, you’ll find that it stores your inputs in a JSON file in the %AppData%\PreferencesExample folder. If you run it again, you’ll see that it pulls your inputs back out of the JSON file to populate the UI.

Let’s take a look at the relevant parts of the source code:

public void LoadPreferences () {
  if (!File.Exists(GetPrefsPath()))
    return;

  var serializer = new JavaScriptSerializer();
  var preferences = serializer.Deserialize<Dictionary<string, object>>(File.ReadAllText(GetPrefsPath()));

  checkBox1.Checked = (bool)preferences["checkBox1"];
  radioButton1.Checked = (bool)preferences["radioButton1"];
  radioButton2.Checked = (bool)preferences["radioButton2"];

  listBox1.SelectedIndices.Clear();
  var indices = preferences["listBox1"] as ArrayList;
  foreach (var index in indices)
    listBox1.SelectedIndices.Add((int)index);

  textBox1.Text = (string)preferences["textBox1"];
  dateTimePicker1.Value = (DateTime)preferences["dateTimePicker1"];
}

public void SavePreferences () {
  var preferences = new Dictionary<string, object>();

  preferences["checkBox1"] = checkBox1.Checked;
  preferences["radioButton1"] = radioButton1.Checked;
  preferences["radioButton2"] = radioButton2.Checked;
  preferences["listBox1"] = listBox1.SelectedIndices.Cast<int>().ToArray();
  preferences["textBox1"] = textBox1.Text;
  preferences["dateTimePicker1"] = dateTimePicker1.Value;

  if (!Directory.Exists(Path.GetDirectoryName(GetPrefsPath())))
    Directory.CreateDirectory(Path.GetDirectoryName(GetPrefsPath()));

  var serializer = new JavaScriptSerializer();
  File.WriteAllText(GetPrefsPath(), serializer.Serialize(preferences));
}

This application is relatively small – in particular, the JavaScriptSerializer handles a lot of the work involved in storing preferences for us. But regardless, we find ourselves having to list out all the control names multiple times, and some of those references to the controls are strings. Since they’re strings, that means that automatic refactoring tools, like the Rename tool in Visual Studio, won’t find them. As a result, this sort of code becomes difficult to maintain, especially in a larger codebase – changes are extremely error-prone and require careful, manual work.

What we want is a way to eliminate this duplication – a way to pull the list of controls and values out and store them in one place, so that we don’t have to specify them multiple times. Unfortunately, there’s no obvious way to do this in either Java or C#. While you can add the controls to a list quite easily, and walk over the list to get control names – eliminating part of the duplication – there’s no clean way to specify the particular fields/properties you wish to store.

Those of you familiar with reflection techniques may realize that you can eliminate the duplication by using reflection. By specifying a control and the name of the field we care about, we can use reflection to find that field and fetch its value. This technique will work, and other than the performance overhead of reflection, it will work well enough to ship in an application. However, it still suffers from the downside of breaking automated refactoring tools, and it’s somewhat error-prone due to the complexity involved in finding fields/properties via reflection.

One of the new features in C# 3.5 is support for ‘Expression Trees‘. Expression trees allow you to convert a C# expression into a tree of objects that describe the expression and allow you to evaluate it. This feature is used to support LINQ – for example, when you write ‘where i < 5′ in a LINQ query, the ‘i < 5′ portion of the query is turned into an expression tree, that LINQ can then use to run the query – for example, by turning it into SQL. As it happens, we can use this feature to solve our problem!

In C# 3.5, virtually any expression we can write can be converted into a delegate using lambda syntax, like so:

Func<int, int> func = (x) => x * 5;

And, as part of the Expression Tree feature, we can convert that lambda into an expression tree, at compile time:

Expression<Func<int, int>> expr = (x) => x * 5;

The compiler provides us all the information we need to evaluate an expression within the expression tree – if the expression references a field, the expression tree will contain the object containing the field, along with the FieldInfo object representing the field. Using this knowledge, we can eliminate the duplication from our sample application: By using a single expression to represent each preference we want to store, we can list all of our preferences in a single place in our application, and use that list of expressions to both load and save preference values. Best of all, because the compiler gives us full information on the expressions, we know the exact data types involved, and we can find out the name of the field being stored, and even the name of the object containing the field – eliminating the need to name each preference manually.

Using this knowledge, we can write a simple helper class that represents a field or property reference, and construct instances of that class by passing it an expression. You can find the source code to the class here:
http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/Bind.cs
And we’ll be using it to eliminate the duplication from our sample application. The code is relatively small – a couple hundred lines – so by reading it you can easily see how to apply this technique for your own purposes, even if you don’t end up using my code.

The first step is to use expressions to build a list of all the values we want to store. We’ll do this by creating an array of bound members in the dialog box’s constructor:

IBoundMember[] BoundMembers;

public MainDialog () {
  InitializeComponent();

  BoundMembers = new IBoundMember[] {
    BoundMember.New(() => checkBox1.Checked),
    BoundMember.New(() => radioButton1.Checked),
    BoundMember.New(() => radioButton2.Checked),
    BoundMember.New(() => listBox1.SelectedIndices),
    BoundMember.New(() => textBox1.Text),
    BoundMember.New(() => dateTimePicker1.Value)
  };
}

Note that all we have to do is create an expression that evaluates to the value we wish to store. The C# compiler will convert it into an expression tree that tells us which object contains the value, and the FieldInfo or PropertyInfo we can use to fetch the value.

To eliminate the need to specify the name of each preference, we can combine the name of the field/property along with the name of the control containing the field/property, like so:

string GetMemberName (IBoundMember member) {
  return String.Format("{0}.{1}", ((Control)member.Target).Name, member.Name);
}

If we specify the Checked property of a RadioButton named radioButton2, this function will evaluate to ‘radioButton2.Checked’.

With these two pieces of functionality, we can now eliminate all the duplication from the old LoadPreferences and SavePreferences functions:

public void LoadPreferences () {
  if (!File.Exists(GetPrefsPath()))
    return;

  var serializer = new JavaScriptSerializer();
  var preferences = serializer.Deserialize<Dictionary<string, object>>(File.ReadAllText(GetPrefsPath()));

  foreach (var bm in BoundMembers)
    bm.Value = preferences[GetMemberName(bm)];
}

public void SavePreferences () {
  var preferences = new Dictionary<string, object>();

  foreach (var bm in BoundMembers)
    preferences[GetMemberName(bm)] = bm.Value;

  if (!Directory.Exists(Path.GetDirectoryName(GetPrefsPath())))
    Directory.CreateDirectory(Path.GetDirectoryName(GetPrefsPath()));

  var serializer = new JavaScriptSerializer();
  File.WriteAllText(GetPrefsPath(), serializer.Serialize(preferences));
}

Another thing you’ll notice is that the type casting from the original version is gone – since we have type information, we can automatically cast preference values to the appropriate type – and if we were using a strongly typed datastore, instead of JSON, we could actually store preferences directly in their correct type, without having to do any boxing or type casting.

If you download the source code for the revised example:
Preferences Example (v2)
You can run it and see that while it works the first time, and correctly saves preferences to JSON, it fails when loading preferences back from JSON. This turns out to be because of the JSON serializer: While listBox1.SelectedIndices is of type SelectedIndexCollection, the list we get back from the JSON serializer is of type ArrayList. The two types aren’t convertible, so the application fails.

Luckily, we can easily solve this problem. Since this technique works for any field or property, we can simply define a property that handles type conversion so that we don’t get an error when trying to load the preference value from JSON, like this:

// This has to be ArrayList since that's what we get back from the JSON serializer
ArrayList ListBox1_SelectedIndices {
  get {
    var result = new ArrayList();
    foreach (var index in listBox1.SelectedIndices)
      result.Add(index);
    return result;
  }
  set {
    listBox1.SelectedIndices.Clear();
    foreach (var index in value)
      listBox1.SelectedIndices.Add((int)index);
  }
}

If we change the list in the dialog box constructor to reference this new property instead of referencing the listbox directly, we can run the application and it will now successfully load and save preferences.
Preferences Example (v3)

With this technique, you can easily handle automatically loading and saving values from almost any datastore – and do so efficiently, without any unnecessary duplication, thanks to the information we’re given by the compiler. As an example, here’s a simple implementation of an object that loads and saves preferences from a database using this technique:
http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/Data/PropertySerializer.cs

I hope this post has shown you something useful! In the future I’ll be showing some other interesting applications of this technique.