65.9K
CodeProject is changing. Read more.
Home

DataStorage: Store settings type-safe

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (3 votes)

Feb 20, 2012

GPL3

3 min read

viewsIcon

26710

downloadIcon

234

Shows how to use the DataStorage classes to generate type-safe settings classes.

Introduction

This article describes the DataStorage classes. They provide type-safe hierarchic settings that can be stored in various formats. Currently, Registry, INI files, and XML are supported.

Using these classes, you will be able to generate settings classes that do the boring work for you. Usually, storing settings involves a lot of repetitive work, calling the same function to read a value, checking the type, casting it, and maybe doing something if the value is missing. The same goes for writing settings and you have to keep the reading and writing parts in sync when things change.

The DataStorage classes allow you to write the settings definitions in XML or build them with the Windows Forms application and then generates all the required classes for you. You can also create a hierarchy of classes, like in this sample:

331288/main_window.png

Background

The idea to the DataStorage came when we were thinking about completely rebuilding PDFCreator from scratch. It was still written in Visual Basic 6 and came to its limits on various points. When designing the new application, it became clear that manually rebuilding all the settings would be a painful job and would not be what we intended to do, so we looked for a better way.

One of the results is the DataStorage. On top of that, we have also built the DynamicTranslator, which will be described in another article later on.

Using the code

The idea was to have a unified way to access settings. The foundation of the DataStorage is a class that simply stores names and values of which all are strings. The names can be hierarchic by adopting the Windows folder syntax.

data.setValue(@"Test\abc", @"my value");

This can be stored by passing it to a writer object:

XmlFiles xml = new XmlFiles();
xml.setData(data);
xml.writeData(@"C:\test.xml");

This is the basic way of storing settings, but nothing is type-safe so far, as we are just using strings.

The DataStorageGenerator shown on the screenshot above does the actual magic. It creates the class hierarchy and all the code required to load and store the data properly.

After generating the above sample, you will receive a class called MySettings and another one called ProjectSettings. You can then store your:

XmlFiles xml = new XmlFiles();
MySettings settings = new MySettings();
settings.saveData(xml, @"C:\test.xml");

The generated class will do all the work for you:

public bool saveData(DataWriter dataWriter, string path) {
    try {
        data.clear();
        storeValues(data);
        dataWriter.setData(data);
        dataWriter.writeData(path);
        return true;
    } catch { return false; }
    
}

public void storeValues(Data data) {
    data.setValue(@"MySettings\LastFolder", LastFolder);
    data.setValue(@"MySettings\IntTest", IntTest.ToString());
    data.setValue(@"MySettings\IsTrue", IsTrue.ToString());
}

The same goes for loading values:

public void readValues(Data data) {
    LastFolder = data.getValue(@"MySettings\LastFolder");
    try { IntTest = int.Parse(data.getValue(@"MySettings\IntTest")); }
      catch { IntTest = 0;}
    try { IsTrue = bool.Parse(data.getValue(@"MySettings\IsTrue")); }
      catch { IsTrue = true;}
}

You can see that this tries to parse the data correctly. If the data should be invalid or missing, the default value will be applied.

That's it so far, but there is one more thing to discover: Custom code sections. No real-world classes are generated and never modified. The custom code sections allow you to add things manually that will not be destroyed when regenerating the classes. This can be includes, custom functions, and so on. The custom sections look like this:

// Custom Code starts here
// START_CUSTOM_SECTION:INCLUDES

  // my custom stuff

// END_CUSTOM_SECTION:INCLUDES
// Custom Code ends here. Do not edit below

Each section has a name (INCLUDES in this case) and will be put in the right spot again. So you can enhance the generated classes without breaking your custom parts. Of course, if you edit code outside the custom code sections, it will be lost.

A last note

I hope you have enjoyed this article. As this is my first one here, I am curious about what you think of the code, the idea behind it, and so on. If I'll find the time, I will also add an article about the DynamicTranslator. It is used for internationalization (i18n) of Windows Forms applications and uses the DataStorage to achieve that. By providing structured translation files, the translation will be applied to the Form by using translation and Reflection, making the work of translating large applications much easier.

There of course are still things to do in this project and it will grow as we make progress with PDFCreator. Most likely we will also set up a SourceForge project or something similar to keep track of everything.

History

  • 2012-02-16: Initial version.