Sunday, October 25, 2009

Hack 48. Extend the Application Configuration File











 < Day Day Up > 





Hack 48. Extend the Application Configuration File





Use an open source custom tool to add your own

configuration sections to your app.config

file
.





Custom configuration sections are a valuable

tool for storing application-specific settings. With .NET, you can

extend the normal configuration files and include your own custom

configuration sections. Normally, creating your own custom

configuration section involves writing classes and a configuration

section handler to access your custom settings. There is an easier

and much quicker way to handle the creation of a custom configuration

section and all the code that you need to work with it.





The open source custom tool, ConfigBuilder, can be used to automatically

generate configuration section handlers, as well as custom objects

that can be used as data containers for the settings.





To use the

ConfigBuilder custom tool, you will need

to download and run the installation file from http://workspaces.gotdotnet.com/configbuilder.







6.6.1. Building the Configuration Template





To start using



ConfigBuilder, you

first need to add a new

XML file to your project. This XML file

is called the configuration template file and

will be used to specify the format of your configuration section.

This file will then used to generate the code to access this

configuration section. The configuration template can be named

whatever you like and should be in the location where you want the

code to be stored. (The code will appear underneath this XML file in

the Solution Explorer, exactly like other custom tool-generated

code.)





The first step to building your configuration template file is to add

a root element named

configuration, the same as a normal

configuration file. Next you will need to declare your custom

sections by creating an element for the section and then any number

of attributes. The name of the section and the name of the attributes

should be the same as the names that will be used in the

configuration section, but instead of specifying values, you will

need to specify the type that this attribute expects. To specify the

type, you will need to use

C# type keywords such as

string, int,

short, and so forth.





Here is an example of declaring a custom section called

DatabaseSettings:





<configuration>

<DatabaseSettings server="string"

username="string" timeout="int" />

</configuration>







In this file, I am creating a single element called

DatabaseSettings that has three different

attributes; the first two are strings and the last is an integer.





You can also define default values for

attributes in the template file.

In this example, suppose that I want to set a default value for the

timeout attribute parameter. I can do this by

simply adding a colon after the type and then specifying my default

value. My template file would now look like this:





<configuration>

<DatabaseSettings server="string"

username="string" timeout="int: 60" />

</configuration>







By declaring a default value, the attribute is no longer required. If

the timeout attribute is omitted in the

configuration section for this application config

file, the code will simply assume the value is 60. (When declaring

default values for strings, you must use [Empty]

to signify an empty string.)





You can also specify the number of times a section can appear, create

section groups, and specify comments to be included in the generated

code. Explanations of these features can all be found in

ConfigBuilder's documentation.









6.6.2. Running the ConfigBuilder





To execute the template file and

generate the code, you need to specify

ConfigBuilder

as the custom tool for this file. This is done by simply entering

ConfigBuilder into the Custom Tool field in

the .XML file's property window

as shown in Figure 6-7.







Figure 6-7. ConfigBuilder set as the custom tool







Once ConfigBuilder is specified as the custom tool for this file, it

will be run every time the file is saved, regenerating the code based

on any changes to the template file.





After you specify ConfigBuilder as the custom tool, a plus sign will

appear next to the .XML file. The plus sign can be expanded to show

the code that has been generated based on the template. Here is a

look at the code generated based on the template from the preceding

example (I have removed comments for the sake of

brevity):





namespace ConfigBuilderExample

{

using System;

using System.Configuration;

using System.Xml;



public sealed class DatabaseSettingsSectionHandler

: object, IConfigurationSectionHandler

{



public const string SectionName = "DatabaseSettings";



public static DatabaseSettingsConfig Config

{

get

{

object oConfig = ConfigurationSettings.GetConfig(

DatabaseSettingsSectionHandler.SectionName);

if ((oConfig = = null))

{

throw new ConfigurationException(

"The application configuration file must have the

\'DatabaseSettings\' configuration" +

" section defined.");

}

return ((DatabaseSettingsConfig)(oConfig));

}

}



object IConfigurationSectionHandler.Create(object parentConfig,

object webContext, XmlNode sectionNode)

{

XmlElement sectionElement = ((XmlElement)(sectionNode));

return DatabaseSettingsConfig.Create(sectionElement);

}



internal static object GetValue(XmlElement element,

string attributeName,

Type attributeType,

string defaultVal)

{

try

{

string attrVal = element.GetAttribute(attributeName);

if ((attrVal.Length = = 0))

{

if ((defaultVal = = null))

{

throw new ConfigurationException(String.Format(

"Missing value for required attribute \'{0}\' of

element \'{1}\'.", attributeName, element.Name));

}

attrVal = defaultVal;

}

if (attributeType.IsEnum)

{

return Enum.Parse(attributeType, attrVal);

}

return Convert.ChangeType(attrVal, attributeType,

System.Threading.Thread.CurrentThread.CurrentCulture);

}

catch (ConfigurationException )

{

throw;

}

catch (Exception ex)

{

throw new ConfigurationException(String.Format(

"Failed to extract value for attribute \'{0}\'

from element \'{1}\'.", attributeName,

element.Name), ex);

}

}

}



public class DatabaseSettingsConfig

{

private String _server;

private String _username;

private int _timeout;



public DatabaseSettingsConfig(String server,

String username,

int timeout)

{

this._server = server;

this._username = username;

this._timeout = timeout;

}



public String Server

{

get{return this._server;}

}



public String Username

{

get{return this._username;}

}



public int Timeout

{

get{return this._timeout;}

}



internal static DatabaseSettingsConfig Create(

XmlElement configElement)

{

String server = ((String)(

DatabaseSettingsSectionHandler.GetValue(

configElement, "server", typeof(String), null)));

String username = ((String)(

DatabaseSettingsSectionHandler.GetValue(

configElement, "username",

typeof(String), null)));

int timeout = ((int )(

DatabaseSettingsSectionHandler.GetValue(

configElement, "timeout", typeof(int ), " 60")));

return new DatabaseSettingsConfig(

server, username, timeout);

}

}

}











6.6.3. Using the Code





To use this

configuration

section in your configuration file, you need to declare your custom

section in the configSections section of the

configuration file for your application:





<configSections>

<section name="DatabaseSettings"

type="ConfigBuilderExample.DatabaseSettingsSectionHandler" />

</configSections>







ConfigBuilderExample is the name of my namespace

in this example. Next, you need to actually add your configuration

section to the application configuration file:





<configuration>

<DatabaseSettings server="localhost"

username="notsa" timeout="55" />

</configuration>







Then you can read these values from the configuration file using the

following code anywhere in your application:





DatabaseSettingsConfig config = (DatabaseSettingsConfig) 

System.Configuration.ConfigurationSettings.GetConfig(

"DatabaseSettings");



MessageBox.Show(config.Server);







The first line of this code gets an instance of the

DatabaseSettingsConfig class from the

configuration file. You can then access any of the configuration

settings by simply accessing the properties of this class. In this

example, the value of the server element is shown to the user through

a message box.





This custom tool is a great time-saver and makes it extremely easy to

create and use custom configuration sections.



















     < Day Day Up > 



    No comments: