Making Application Configuration Easier Using the Castle DictionaryAdapter
Introduction
Before I show you how to use the DictionaryAdapter component, let's briefly recap how you can use the appSettings element. First, take a look at a quick example of the element that you could have in your web.config file:
<appSettings> <add key="MailFromName" value="Your Public Site Name" /> <add key="MailFromAddress" value="you@yourprovider.com" /> <add key="SendMailOnError" value="true" /> </appSettings>
You can then use these settings in a few different ways. For example, you can access them using expression syntax, and programmatically. The following example access the MailFromName setting and assigns it to a label using expression syntax:
<asp:Label ID="Mail" runat="server" Text="<%$ AppSettings:MailFromName %>" />
When added to a page, this label shows the text "Your Public Site Name".
To access the values stored in web.config and assign it to the same label through code, you use the WebConfigurationManager class like this:
C# Mail.Text = WebConfigurationManager.AppSettings.Get("FromAddress");
VB Mail.Text = WebConfigurationManager.AppSettings.Get("FromAddress")
The problem with this latter solution is that it gets messy quite quickly. First, you need to write this code every time you need it. Secondly, and more importantly, it doesn't deal with error handling very well (when a key is missing for example), and doesn't provide an easy way to supply a default value. That's why I typically add static and read only properties to a class in my project that serve as wrappers around the appSettings element. The following code snippet shows a quick example:
C# public static class WebConfiguration { /// <summary> /// "Old way" property that returns MailFromName. /// </summary> public static string MailFromName { get { string temp = WebConfigurationManager.AppSettings.Get("MailFromName"); if (!string.IsNullOrEmpty(temp)) { return temp; } throw new InvalidOperationException( "Can't access key MailFromName in web.config."); // Alternatively, return a default value // return "Your Public Site Name"; } } } VB Public NotInheritable Class WebConfiguration ''' <summary> ''' "Old way" property that returns MailFromName. ''' </summary> ''' <value></value> Public Shared ReadOnly Property MailFromName As String Get Dim temp As String = WebConfigurationManager.AppSettings.Get("MailFromName") If Not String.IsNullOrEmpty(temp) Then Return temp End If Throw New InvalidOperationException( "Can't access key MailFromName in web.config") ' Alternatively, return a default value ' Return "Your Public Site Name" End Get End Property End Class
With this code, you can now assign the MailFromName property to a Label like this:
C# Mail.Text = WebConfiguration.MailFromName; VB Mail.Text = WebConfiguration.MailFromName
When the key does not exist, you get a descriptive error message, enabling you to fix the problem as soon as possible (or you get a default value if you modify the property to return one when they key is not found).
While this solution is a lot better than accessing WebConfigurationManager.AppSettings directly, it still suffers from a few problems:
- The property code contains string literals that map to the keys in web.config. When the two don't match, you may end up with bugs that are hard to track.
- For each configuration key you add to web.config, you need to add the property code as shown here, over and over again. While you could abstract away some of the logic to a separate class or method, you still end up with a lot of repetitive and difficult to maintain code.
Introducing Castle DictionaryAdapter
Fortunately, there is an easy way to fix this, using Castle's DictionaryAdapter. The DictionaryAdapter is part of the open source Castle project, an "open source project for .net that aspires to simplify the development of enterprise and web applications". The DictionaryAdapter lives up to that promise by making it easy to wrap your configuration keys through easy accessible properties, based on the definition of a custom interface.
To get started with the DictionaryAdapter, follow these steps:
- Download the DictionaryAdapter Component from the Castle web site.
- Extract the Castle.Components.DictionaryAdapter.dll assembly to a folder on your hard drive and from a web project (or any other .NET project) add a reference to it.
- Create an interface that defines the names and types of the properties you want to expose. In my case, I added an interface that looks like this:
C# public interface ISettings { string MailFromName { get; } string MailFromAddress { get; } bool SendMailOnError{ get; } } VB Public Interface ISettings ReadOnly Property MailFromName() As String ReadOnly Property MailFromAddress() As String ReadOnly Property SendMailOnError() As Boolean End Interface
- Create a class that serves as the configuration wrapper (called WebConfiguration for example) and add the following code:
C# public static class WebConfiguration { static ISettings _settings; /// <summary> /// Returns the current configuration settings for this web site. /// </summary> public static ISettings Current { get { if (_settings == null) { var factory = new DictionaryAdapterFactory(); _settings = factory.GetAdapter<ISettings>( WebConfigurationManager.AppSettings); } return _settings; } } } VB Public NotInheritable Class WebConfiguration Private Shared _settings As ISettings ''' <summary> ''' Returns the current configuration settings for this web site. ''' </summary> Public Shared ReadOnly Property Current() As ISettings Get If _settings Is Nothing Then Dim factory = New DictionaryAdapterFactory() _settings = factory.GetAdapter(Of ISettings) _ (WebConfigurationManager.AppSettings) End If Return _settings End Get End Property End Class
The code uses static variables to create a singleton Current property that serves as the main configuration entry point for the entire application. Assigning one of the values from the appSettings element to a Label can now be done like this:
C# Mail.Text = WebConfiguration.Current.MailFromName; VB Mail.Text = WebConfiguration.Current.MailFromName
Downloads
- Download fully functional example sites in VB and C#. The projects are created with Visual Studio 2010 and target .NET 4, but the code should run on earlier versions of .NET as well.
Where to Next?
Wonder where to go next? You can post a comment on this article.
Links in this Document
Doc ID | 550 |
Full URL | https://imar.spaanjaars.com/550/making-application-configuration-easier-using-the-castle-dictionaryadapter |
Short cut | https://imar.spaanjaars.com/550/ |
Written by | Imar Spaanjaars |
Date Posted | 07/30/2010 14:17 |
Comments
Talk Back! Comment on Imar.Spaanjaars.Com
I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.
When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.
If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the Doc ID of the document.