![]() |
Languages »
C# »
Applications
Intermediate
Strongly Typed Configuration Class Generator for VS.NETBy nidhoggBased 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. |
C#.NET 1.0, .NET 1.1, Win2K, WinXP, Win2003VS.NET2003, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||

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:
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.
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:
<defaultNamespace>.<fileName>.Settings to access the settings. Note how Intellisense displays the properties along with comments.
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.
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.
<% 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.
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.
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.
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.
Latest versions will be posted on my weblog and on Code Project. Feel free to post comments or suggestions.
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.
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 6 Jun 2004 Editor: Nishant Sivakumar |
Copyright 2003 by nidhogg Everything else Copyright © CodeProject, 1999-2009 Web12 | Advertise on the Code Project |