IntelliSense for custom ConfigurationSections

To be frank: I don’t like XML for configuration purposes. I think it’s a plague and nothing less. It is verbose and prone to typos. It does not give you any type safety. Thus I wage a constant war against XML config files in my projects.
But sometimes you can’t avoid XML for one reason or another. And if you can’t avoid it you have to cope with its shortcomings. Configuration in code gives you (among many other things I value) IntelliSense support. You get help with possible values for variables, properties or parameters, method names and much more. To get (some of) the same convenience for config files you have to provide xsd schema files. Established frameworks sometimes ship with those schemas. But if you write custom config sections you are completely on your own.

Rob Seder has a great post on writing custom configuration sections. The last paragraph explains how you can create xsd’s for your components.

While playing with Enumeration Classes I also wanted to see how I can use them with config files. So I wrote a custom config section for evaluation purposes.

public class MyConfigSection : ConfigurationSection
{
  private readonly ConfigurationProperty myEnum;
  public MyConfigSection()
  {
    this.myEnum = new ConfigurationProperty(
      "myEnum", 
      typeof(Numbers),
      Numbers.None,
      new EnumClassConverter<Numbers>(),
      null,
      ConfigurationPropertyOptions.IsRequired);
    this.Properties.Add(this.myEnum);
  }
  public Numbers MyEnum
  {
    get { return (Numbers)base[this.myEnum]; }
    set { base[this.myEnum] = value; }
  }
}

Numbers is an enumeration class from a prior article.

[side note] I love the way Microsoft’s engineers allow you to control how the configuration system handles your custom classes by letting you specify a TypeConverter [/side note]

I followed the steps outlined in Rob’s post and created a schema using the XML –> Create Schema option from Visual Studio. I stripped away all the fluff that belonged to the config file schema until all that was left was the part for my custom section. I then added comments and allowed values for Numbers along with some more comments. I ended up with the following xsd.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           targetNamespace="http://tecx.codeplex.com/tecx/2012/enum"
           attributeFormDefault="unqualified"
           elementFormDefault="qualified">
  <xs:element name="mySection">
		<xs:annotation>
			<xs:documentation>This demonstrates IntelliSense for config files</xs:documentation>
		</xs:annotation>
    <xs:complexType>
      <xs:attribute name="myEnum" use="required" >
        <xs:annotation>
          <xs:documentation>Predefined set of numbers</xs:documentation>
        </xs:annotation>
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="None">
              <xs:annotation>
                <xs:documentation>NaN</xs:documentation>
              </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="One">
              <xs:annotation>
                <xs:documentation>Number 1.</xs:documentation>
              </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Two">
              <xs:annotation>
                <xs:documentation>Number 2.</xs:documentation>
              </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Four">
              <xs:annotation>
                <xs:documentation>Number 4.</xs:documentation>
              </xs:annotation>
            </xs:enumeration>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>
</xs:schema>

That’s a lot of xml for one single property but there you are… One important thing to notice is the targetNamespace attribute in the schema element. This will be used to reference the schema in your config file.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="mySection" type="TecX.EnumClasses.Test.MyConfigSection, TecX.EnumClasses.Test"/>
  </configSections>
  <mySection myEnum="Four" xmlns="http://tecx.codeplex.com/tecx/2012/enum" />
</configuration>

The section contains a reference to the targetNamespace of your custom schema. Now you need to add the xsd to the list of schemas for your config file. VS did that automatically for me when I placed the schema file in the same folder as the config file. If your’s doesn’t you can add the schema manually. Right click in the editor window for your app.config, select Properties from the context menu and the properties view will show up. It lists a setting called Schemas where the path to the DotNetConfig.xsd will already be listed. Click the […] button and add your custom schema using the dialog that pops up.

IntelliSense for custom configuration sections

And finally Visual Studio will give you some help with the tedious task of handling configuration through XML.

On top of writing the code for the configuration section you have to put some effort into writing the schema. I would not make that investment until the API is mostly stable for the current release. But then it definitely makes sense and developers that use your components will love you for that. Its the kind of documentation that does not force them to leave their working environment, lookup something in a .chm help file or a wiki page but instead they can stay focused on their current task.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: