Click here to Skip to main content
15,893,161 members
Articles / Programming Languages / C#
Article

Strongly Typed Configuration Class Generator for VS.NET

Rate me:
Please Sign up or sign in to vote.
3.44/5 (7 votes)
6 Jun 20046 min read 83.3K   2.3K   50   4
Based on an XML file containing your application settings, this tool automatically generate a strongly typed class that can read and write values to the file.

Sample Image - ConfigGenerator.png

Introduction

In the .NET environment there are few things left that are not strongly typed. The application settings, based on the .config files are one of them. When you access the settings through ConfigurationSettings.AppSettings, the .NET framework requires a string identifier to get the item you need from the .config file. Moreover, what you get is a generic object that you need to cast into the right type before you can use it. The problem is that errors in the identifier or the type, only show at runtime. I thought it would be nice to be able to detect these errors at compile time.

During the short analysis part of this project, I determined a few other requirements /nice features:

  • Full integration to Visual Studio .NET
  • Ability to write values
  • Intellisense, complete with comments when accessing settings values
  • Detect changes made to the XML file

Background

I had this idea while using strongly typed DataSets. I got curious about how VS.NET generated a .cs file from the XML schema, so I did a little research. The answer is that it uses a custom tool. If you have not heard of custom tools, I suggest you read Chris Sells' article on MSDN about Visual Studio .NET's top 10 cool features.

Apparently, Microsoft changed its mind about letting VS.NET users write their own custom tools. The interfaces and base classes that were public in VS.NET 2002 disappeared in VS.NET 2003. Since some people already had code that used these interfaces, they released the source code on GotDotNet. If you ever want to write a custom tool, get this file.

Another interesting tidbit about this project is the integration of new file types in VS.NET's "Add new item..." dialog. I wanted to be able to add a special file to my project, define the values and types I wanted to access, and have the custom tool do the rest. Fortunately Chris Sells has another article on how to add your own file types to VS.NET.

After a bit of prototyping, it became clear that I would need to generate quite a bit of code. CodeDom could have been a good solution, but having used it a bit, I knew it would be a real pain to code that part. So I decided to use CodeSmith instead. It is a code generator that relies on a ASP.NET-like syntax and you can use its engine in your code. You will need to download and install it to get this tool to work.

Usage

I decided to forget about .config files and use a simple XML file so as not to interfere with the existing System.Configuration classes and give me more flexibility. The schema for the XML file is extremely simple: each settings value is described in an <Entry> tag that has a name, a type, a value and an optional comment. Arrays are supported via the <Set> and <Item> tags. Look at the example file to get a better idea of how it works.

The tool works as follows:

  1. Add a special item to your project (Config file in the Utility section). In fact it is an XML file (name .xfg) based on the simple schema described above. VS.NET automatically assigns the custom tool to it so that each time you save it, it will generate a hidden .cs file with the class to access the values. You can see this file if you click on "Show all files" in the solution explorer. If the XML file is malformed, errors will show in the tasks pane.
  2. Edit this file, add entries, sets etc. required by your application.
  3. The generated class has the same name as the .xfg file and is in the project's default namespace. Use <defaultNamespace>.<fileName>.Settings to access the settings. Note how Intellisense displays the properties along with comments.
  4. Compile. Any type mismatch and syntax errors will cause the compilation to fail and you'll be able to correct them before running the application.
  5. Make sure the .xfg file is located at the same place as the assembly and run.

The code

There is not much code involved in making such a custom tool. You simply write a class that inherits from the BaseCodeGeneratorWithSite class you got from GotDotNet and override the GenerateCode method. Since I use CodeSmith, I only need to set it up and run it with a template that will generate the class to access the settings. Most of the interesting code is in the template and the resulting generated code.

Template code

The trick here is to clearly separate in your mind the generator code from the generated code. Since they are mixed in a single ASP.NET-like file it is easy to lose track of it. As an example, here is the part of the template that generates the strongly typed properties for each entry in the XML file. The parts in <% %> contains generator code. The rest is generated code, just like ASP.NET. The doc variable is an XmlDocument that contains the settings file.

C#
<% foreach(XmlNode n in doc.SelectNodes("/Configuration/Entry"))
{%>
  private <%=n.Attributes["Type"].Value%> m_<%=n.Attributes["Name"].Value%>;
  <% if(n.Attributes["Description"] != null)
  {
  %>
  /// <summary>
  /// <%=n.Attributes["Description"].Value%>
  /// </summary>
  [Description("<%=n.Attributes["Description"].Value%>")]
  <%
  }%>
  [Category("Values")]
  public <%=n.Attributes["Type"].Value%> <%=n.Attributes["Name"].Value%>
  {
      get { return m_<%=n.Attributes["Name"].Value%>; }
      set { m_<%=n.Attributes["Name"].Value%> = value; }
  }

<%
}
%>

You can analyze the rest of the template and particularly the Refresh and Save methods in the TypeConfig.cst file. If you want to, you can also modify the template to alter the generated code to your liking. Changes to the template file are taken into account immediately by the tool, so you can modify it and test without having to recompile.

Generated code

Like System.Configuration.ConfigurationSettings.AppSettings, I wanted a single access point, so I used a singleton pattern. This way, it would require less code to access the settings and possibly reduce threading problems. The constructor is private and you can only get one instance through the static Settings property.

C#
private static Config1 m_settings;
public static Config1 Settings
{
    get 
    {
        if(m_settings == null)
            m_settings = new Config1();
        return m_settings;
    }
}

//[...]

private Config1()
{
    /// [...]
}

In order to monitor changes made to the configuration file externally, a FileSystemWatcher object is created and made to look for any modification made to the file. When it detects a change, it fires the FileChanged event.

The Refresh method reads the file and uses XPath to read the values and store them in private fields. The Save method writes the values in the file.

The class also inherits from Component. It enables the VS.NET designer and property grid to access settings visually, if an instance of the generated class is dropped on a form for example. The singleton pattern disrupted that idea but it could be helpful.

Points of interest

The most difficult aspect of this project was certainly the installation procedure required to integrate it to Visual Studio correctly. There are files to put at the right place, registry keys to read to determine where to put the files, components to register etc. I used NSIS (Winamp's installer) for that, because it is powerful but it is also fairly difficult to use. The install script and files required to generate the installer is included in the source package, in case you want to have a look at it.

Updates

Latest versions will be posted on my weblog and on Code Project. Feel free to post comments or suggestions.

Downloads

NOTE : The source code package contains only the source code which in itself is not functional. You need to run the installer to get the tool to work.

History

  • July 17, 2003 : initial release, build 1271.
  • June 02, 2004 : added xml schema to get Intellisense when editing the config file. Also added a demo application.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralExample Pin
Technorat29-May-04 0:41
Technorat29-May-04 0:41 
GeneralRe: Example Pin
nidhogg1-Jun-04 3:32
nidhogg1-Jun-04 3:32 
GeneralApp.xfg Pin
Thierry Bouquain21-Jul-03 3:29
Thierry Bouquain21-Jul-03 3:29 
GeneralRe: App.xfg Pin
Anonymous25-Sep-03 10:45
Anonymous25-Sep-03 10:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.