Configuration is a breeze.

Published 14 April 04 01:59 PM | ScottSeely 

In the current Visual Studio .NET 2005, you’re going to find that a great thing has happened to configuration. Basically, the mechanism for creating, editing, and parsing configuration sections just got really easy. If this particular item snags a bit of interest, I’ll go as deep as I can in future posts. Here is a teaser to see if there is any real interest.          

Let’s say that I have a reason for configuration. The data I need to store happens to be the following:

  • A string
  • An integer
  • A TimeSpan (for timeouts?)

Let’s say that I want the serialized format to look like this:

<mySpecialSection someString=”value” someInteger=”9” timeout=”00:12:30”/>

Previously, I would have to write a bunch of code that parsed an XML stream and sorted the data into the right data members. Today, the code to read and write the above looks like this:

using System;

using System.Configuration;

using System.Reflection;

 

public class MySpecialSection : ConfigurationSection

{

    [ConfigurationProperty(MySpecialSection.configSomeString,

        DefaultValue = "default")]

    public string SomeString

    {

        get { return (string)base[MySpecialSection.configSomeString]; }

        set { base[MySpecialSection.configSomeString] = value; }

    }

 

    [ConfigurationProperty(MySpecialSection.configSomeInteger,

        DefaultValue = 1)]

    public int SomeInteger

    {

        get { return (int)base[MySpecialSection.configSomeInteger]; }

        set { base[MySpecialSection.configSomeInteger] = value; }

    }

 

    [ConfigurationProperty(MySpecialSection.configTimeout)]

    public TimeSpan Timeout

    {

        get { return (TimeSpan)base[MySpecialSection.configTimeout]; }

        set { base[MySpecialSection.configTimeout] = value; }

    }

 

    const string configSomeString = "someString";

    const string configSomeInteger = "someInteger";

    const string configTimeout = "timeout";

}

Then, to write out the configuration AND make sure that this section was included in the right configuration file, you would have this:

public class App

{

      static public void Main(string[] args)

      {

        Configuration config = Configuration.GetExeConfiguration(

           Assembly.GetExecutingAssembly().Location,

           ConfigurationUserLevel.None);

 

        //Load my section from config

        MySpecialSection section = config.Sections["mySpecialSection"]

            as MySpecialSection;

        if (section == null)

        {

            // The section wasn't found, so add it.

            section = new MySpecialSection();

            section.RequireDeclaration(true);

            config.Sections.Add("mySpecialSection", section);

        }

        section.Timeout = TimeSpan.FromMinutes(4);

        section.SomeInteger = 15;

        section.SomeString = "Hello!";

 

        // Save the changes.

        config.Update();

    }

}

The output of the above is:

<?xml version="1.0" encoding="utf-8"?>

<configuration>

    <configSections>

        <section name="mySpecialSection" type="MySpecialSection, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />

    </configSections>

    <mySpecialSection someString="Hello!" someInteger="15"

        timeout="00:04:00" />

 </configuration>

Not bad! I don’t know how you are configuring your applications today, but this particular model is nice. This particular OM has a few other benefits as well. For example, calls to ConfigurationSettings.GetConfig always succeed for configuration sections that are implemented by a ConfigurationSection-derived class. No more checking for null and filling in your defaults from some other area. Instead, you set the default values in your ConfigurationSection.

Why have the default values in the ConfigurationSection? Doing so provides the following benefits:

  1. If the user is happy with the default value, this is what you read back.
  2. If the user sets the setting to the default value, the configuration system writes out nothing. It’s also faster to read back the default setting since it takes zero time to read nothing.

I’ve been using this framework to develop a lot of configuration code for Indigo, System.Net, and System.Transactions. If you have stayed away from config up until now, give this stuff another look. You’ll be pretty happy!

By the way, at runtime when your application is reading the settings you would still load the settings using ConfigurationSettings.GetConfig(”mySpecialSection”).

Comments

# Phil Weber said on April 14, 2004 2:39 PM:
> ConfigurationSettings.GetConfig(”mySpecialSection”)

Nooo! I want strong typing, e.g.:

ConfigurationSettings.mySpecialSection

Please? :-)
# Scott Seely said on April 14, 2004 3:15 PM:
ConfigurationSettings.GetConfig returns something of type object. You need to know what to cast the returned value to. From there, it's all strongly typed.
# Gabe Anguiano said on April 14, 2004 3:22 PM:
Scott,

I noticed yesterday that with VS.NET 2005 on Longhorn with the SDK that if the project doesn't compile it deletes the Debug directory (over the network).

If it does this then it also deletes the exe.config. Is this intended? If so, it makes it a bit hard to use exe.configs.

BTW, the project is over a network share.

# Scott Seely said on April 14, 2004 3:37 PM:
Since VS.NET 2001 (and maybe even in the betas), the following should work:
1. In your solution, add a new Xml file and name it app.config.
2. Edit app.config.
3. Build as needed. When you build, app.config gets copied to the target build directory as [appname].exe.config.

# Drew Marsh said on April 14, 2004 3:43 PM:
This is just as nice as typed ResourceManager wrappers. Kudos to MS for the good work on VS.NET's productivity features.
# Kevin Dente said on April 14, 2004 4:30 PM:
Cool stuff. Have you looked at Craig Andera's post on the subject of config sections?
http://staff.develop.com/candera/weblog2/PermaLink.aspx?guid=1b6b0694-653b-41c8-9e10-2d8b37a887db

He's got some interesting thoughts, and I think his approach has some cool benefits. Personally, I've always felt that having the type name embedded in the config file isn't totally ideal.
# Gabe Anguiano said on April 14, 2004 5:58 PM:
Thanks for the tip!!! BTW - excellent blog and timing. I was just about to write my own config class from scratch, this will same me a lot of time.
# David A. Mellis said on April 14, 2004 6:19 PM:
Will there be a way to read configuration settings from an arbitrary file or XmlReader? It's very limiting to have to put everything in the global configuration file.
# Scott Seely said on April 14, 2004 7:38 PM:
David: I assume that you are asking about whether or not the settings have to go into machine.config. The settings most certainly can go into a app.exe.config or web.config too.

In the next few days I'll try to write something up about accessing/editting the various config files.
# Martin Naughton said on April 15, 2004 5:45 AM:
Hi,

Any news on support for .DLL assemblies?

What I mean is, if my application comprises MyApp.exe, dependent on MyLib.dll (in the same folder), can I have a MyLib.dll.config file for settings specific to MyLib.dll?

More generally, can I access arbitrary .config files, e.g. MySettings.config, where the app is not called MySettings?

Also, did I read your note correctly, in that it will be possible to write back to the config file? I thought this was disallowed by design in .NET 1.x.

Thanks,
Martin
# John Lewicki said on April 15, 2004 9:48 AM:
Phil,

If you are interested in strong typing you may be interested in a tool I wrote. It is essentially is a code generator that will generate code equivalent to the ConfigurationSection that Scott is describing in his blog, but with strongly typed accessors. An appropriate IConfigurationSectionHandler implementation is generated as well.

You can get at your configuration data by something like:

string someString = MySpecialSectionHandler.Config.SomeString;


http://www.gotdotnet.com/Community/Workspaces/workspace.aspx?id=d7cfbcd5-5963-45db-9755-17dc429164bb

-John
# Stefan Rusek said on April 15, 2004 12:45 PM:
Shouldn't GetExeConfiguration() be GettAssemblyConfiguration()? it seems like Exe goes away from the naming scheme already inuse in the framework.
# Scott Seely said on April 15, 2004 1:12 PM:
Martin: First, there is no support for DLL specific config. Second, yes, you can write back to the config file. I'm working on a post now that describes what goes on here. Look for it in the next couple of days.
# Martins said on April 16, 2004 9:33 AM:
Actually, I would not write the class "MySpecialSection" manually.

1. Write a XmlSchema for your config file.
2. Generate it using "xsd.exe"

You are set + you get automatic config validation.
# Scott Seely said on April 16, 2004 12:22 PM:
Martins: I see that there is a need for a backgrounder on the "why" behind the feature as well. Even in v1.x of the .NET Fx, I wouldn't have agreed with you. Your particular solution won't support the merge behavior that is required for configuration sections, meaning that users of your particular approach would have unexpected results if they set parts in machine.config and other parts in app.config or web.config.

As a second issue, your solution would not get the benefits of remote administration or store agnostic serialization that you can get by using the ConfigurationSection class and its relatives.
# ScottSeely's WebLog said on April 21, 2004 1:37 PM:
# Sean Hernandez said on July 29, 2004 9:47 AM:
The code that reflects over ConfigurationPropertyAttribute has a bug in VS2005 Beta
Anonymous comments are disabled

Search

This Blog

Tags

No tags have been created or used yet.

Syndication

Page view tracker