Configuration Manager for the Enterprise

SysConfiguration is a component that allows the storing of configuration data for an enterprise application. It is intended to be an improved version of the System.Configuration class or the Enterprise Library (Microsoft Patterns and Practices).

Introduction

SysConfiguration is a component that allows storing of configuration data for an enterprise application. It is intended to be an improved version of the System.Configuration class or the Enterprise Library (Microsoft Patterns and Practices).

Enterprise Configuration

I work for a group at T4G Limited, which creates complex custom applications for large enterprises. It's not uncommon that a single application has multiple user interfaces (consumer, call center, B2B, etc.). As a result, we often have multiple architectures (web, Web Services, WinForms, COM+, etc.) running in parallel. As a technology services company, there is a high degree of requirement volatility, which means we have frequent deployments to multiple environments (Development, Test, Staging, User Acceptance Testing, Production, etc.). In line with the types of projects we do, the goals of this component were:

Automatically detect if a configuration setting was missing

Problem: A big frustration with the App.Config is that it's loosely typed. This means that if there is a setting that is used by a component, you have to actually test that component before you can determine whether it's there or not.

Solution: SysConfiguration uses a strongly typed class. The very first time it's loaded, it will validate the configuration data against a schema to ensure that all mandatory settings are there, while still allowing for optional settings. This is a huge benefit when moving code through the environments (e.g., Development to Testing to Production).

Works for multiple architectures

Problem: If you have an application that has multiple architectures, each one stores their configuration in different places: Web.config for web applications and Web Services, App.config for WinForms and console applications, Registry for COM+, etc. The Enterprise Library does have the FileConfigurationSource class, which allows you to call a centralized configuration file, which is an improvement over the default .NET Framework.

Solution: SysConfiguration can use the same file for all architectures. The only difference is the location of two entries that point to the location of the configuration file and the schema that validates it. This provides a degree of flexibility, because systems can share the same configuration, or point to different locations if you want to keep them distinct.

Strongly typed hierarchical data

Problem: Although you can create hierarchies with System.Configuration, when you actually access a property, you still have to use AppSettings["LooselyCoupledKey"]. This does not allow typos to be detected at compile time, only at runtime.

Solution: SysConfiguration generates a hierarchical object model that represents the configuration class. This means you get code that is easy to understand, caught at compile time, and can use IntelliSense (e.g.: SysConfiguration.Data.AppConfig.ConnectionStrings.Core).

Standardized configuration entries

Problem: At T4G, we tend to share components whenever we can. If you want to pass a component to another person, it would be desirable to reliably pass the configuration entries specific to that component. If you use something like App.Config, all you can do is hope that somebody has commented it well enough to indicate which settings belong to which components.

Solution: SysConfiguration is designed in a way that the hierarchical structure of the configuration can be broken up into many files. For example, they could be broken up into: AppConfig, which stores settings that are specific to the current application, T4GToolbox, which stores all of the settings for our re-usable framework, and RightsConfig which stores the settings for a re-usable security component, etc. SysConfiguration is designed to merge all of these definitions into a single configuration file, so there is only one file to maintain per environment.

Flexible Singleton

An ideal Design Pattern for storing configuration data is the Singleton. You want the configuration data to be loaded from disk once and then kept somewhere fast so that it can be accessed quickly. The problem with the Singleton is that almost all the examples just keep it in memory. If this was used in a web context, the memory would be cleared every time the Application Pool or process recycles the memory. If it was used in COM+ components, it would release that memory as soon as it was idle for a period of time.

SysConfiguration detects the context it is running as, and then stores it in an appropriate storage:

For web applications and Web Services, it uses the Web Cache.

For WinForms and Console applications, it uses memory.

For COM+, it uses the Shared Property Manager.

Test Driven Development

I also wanted to mention that this project was entirely built using Test Driven Development (TDD). Although I probably didn't follow the principles of "You Ain't Gonna Need It" (YAGNI) as closely as I could have, I feel it was the correct balance of optimization and future use. Although I've used TDD for components before, I used this project as a test bed for some of the claims made by proponents of TDD and see for myself whether they are true. See Conclusions about Test Driven Development.

In terms of the process I followed, I consistently wrote the test first, failed it (red), got the code to work according to the test (green), refactored the unit test, and started the cycle all over again.

I've included all the unit tests, which may be of interest because I feel I built out a fairly good process when testing a single component across all the architectures. The most important design decision is that there are a set of tests, called by NUnit, but in many cases, those tests call other tests residing in different processes. So, there is a central assembly that NUnit calls, but the actual unit testing logic is stored somewhere else. This ensures I can call all of the unit tests at once any time I need to.

Using the Code

The install includes optional steps depending on your goals. The first set of steps are for those people who are interested in the configuration component. The second set of steps are additional steps, if you want to learn more about Test Driven Development.

I should mention, there are some manual steps for setting this up, but once it has been integrated, it is very easy to maintain.

Pre-Requisites for SysConfiguration

The project was built using the .NET Framework 2.0 and Visual Studio 2005.

Install NUnit 2.2 from the bin directory of NUnitASP. You will be able to run both NUnits in parallel.

I had to add <supportedRuntime version="v2.0.50727" /> to nunit.exe.config and nunit-console.exe.config. You may have to do the same depending on the .NET runtimes installed on your machine.

You will need to be on an Operating System that supports Component Services or COM+. There is a class with tests that are installed using the regsvcs.exe command line tool.

There are some constants in UnitTestCommon\Constants.cs that will have to be changed. These are set to paths that it expects back, which may differ from your file system. You should be able to figure these out the first time you run the unit tests and it fails.

Open the properties for the UnitTests project. Go to Debug. Choose the Start Action to be "Start External Program". Select the latest version of nunit.exe.

Open up the properties for the WebTestHarness project. Go to Web. Select "Don't open a page. Wait for a request from an external application."

Open the solution properties. Go to Startup Project, select "Multiple startup projects", and choose "UnitTests" and "WebTestHarness" to both start.

Adding SysConfiguration

The project is not designed as a standalone component. There is a class that is automatically generated based on the schema file each time the project is built. This file is then compiled along with the rest of the project. Therefore, it needs to be added to the solution of your application.

If you don't care about unit tests, copy the configuration project into your solution.

If you want the unit tests, copy the configuration project to your main solution. Copy all of the other projects to wherever you are keeping your unit tests. In my case, I kept them in a folder in my solution so there is a clear separation. See SysConfigurationWithUnitTests.sln for an example.

You will have to configure your application to find the configuration file and the schemas that validate it.

If it is a COM+ component, SysConfiguration needs to use the Registry to find the paths. There is a sample .reg file SetupComPlus.reg provided. It will put two keys (ConfigurationPath and ConfigurationSchemaPath) into the HKEY_LOCAL_MACHINE\SOFTWARE\Name.Randar key.

For any web based application, add the following to the Web.config and point the paths to the correct location. For a .NET application, make the same changes, but to the App.config.

<?xmlversion="1.0"?><configuration><!-- Add these items to your configuration file and point them
at the location that has the configuration and schema--><appSettings><!-- Development Configuration Path --><addkey="ConfigurationPath"value="C:\Projects\SysConfiguration\Code\Configuration\
Development\Configuration.xml"/><!-- Production Configuration Path --><!-- <add key="ConfigurationPath"
value="C:\Projects\SysConfiguration\Code\Configuration\
Development\Configuration.xml" /> --><!-- Path to Schema used to validate configuration files--><addkey="ConfigurationSchemaPath"value="C:\Projects\SysConfiguration\Code\
Configuration\Schemas\Settings.xsd"/></appSettings></configuration>

If there are dependent schemas, you will have to change the absolute paths of xs:include in Settings.xsd. There does not seem to be a way to make the path relative, which is unfortunate. I would recommend you try to keep the same file structure on disk across the various environments (development, staging, etc.), or make sure to not overwrite your Settings.xsd when you update the code.

SysConfiguration Tasks

The following is a "help file" of common tasks you would need to perform to use SysConfiguration.

To add a configuration element

The following describes the steps to add a new configuration setting to the application, once the pre-requisite steps have been followed. SysConfiguration is designed to allow developers to quickly add new configuration settings and allow them to define the validation required.

If you would like to add a configuration element, simply change the definition in one of the schemas (e.g., AppConfig.xsd, RightsConfig.xsd, etc.). Do not add configuration elements to Settings.xsd. This is a central hub of the various configuration definitions. It will generate a class that has all references to all the other configuration files. Similar in concept to a project file.

The following are some examples that are supported:

Data types. If you set the type of an xs:element, it will create a valid .NET type.

minOccurs and maxOccurs. These allow you to create collections if maxOccurs is unbounded, and optional settings if minOccurs is 0.

To add configuration data

Once the structure has been defined, the following are the steps to add configuration data:

Open up Configuration.xml in your favourite XML editor. If you are using Visual Studio, it should have the targetNamespace setup so that Intellisense will allow you to build the hierarchy and add the data.

To access a configuration element

Once the configuration definition has been defined, and the data added, the following describes how the application would access that data:

Add a reference to Name.Randar.Configuration.dll.

Add a using statement for the namespace (e.g.: using Name.Randar.Configuration).

Access the configuration hierarchy, starting with the Singleton called SysConfiguration. You can access the data either through the static Data or Instance.SettingsData. Both are identical. Some examples:

To access a list of configuration elements

SysConfiguration supports single name\value pairs as well as lists. The following describes how to access a list of data:

It stores lists as a strongly typed sub-class of the ArrayList class. So you can access it by index or by iterating through the list:

SysConfiguration.Data.RightsConfig.RightCollection[0].Name

SysConfiguration.Data.RightsConfig.RightCollection.Count

// Search through the roles until you find the one we are looking
int findRole = -1;
for (int i = 0; i < settings.RightsConfig.RightCollection.Count; i++ )
{
if (settings.RightsConfig.RightCollection[i].Name == Constants.RoleToSearchFor)
findRole = i;
}

To add a configuration definition

If you would like to extend the configuration definition, but leave the main definition alone, you can use xs:include to include other schemas. This allows you to break up the configuration definition based on components or other requirements.

Create your schema that defines your configuration. Make sure it has a root element.

Modify Settings.xsd:

Add an xs:include and point it at the new file.

Create an element that references the base element of the other schema file.

To reload the configuration data

You should setup your application so there is a way to clear the cache and force it to re-load the data next time it is used. Otherwise, you will have to restart the process somehow to clear the data. The following steps describe how this can be done:

You will have to create something that can be called manually. For example:

A web page in an admin area with a button called "Clear Cache".

A Web Service with a web method called "ClearCache".

A button on the Help->About screen that has a button "Reload Configuration".

In all of these cases, the method should call SysConfiguration.ClearCache().

Out of Scope

The following scenarios have not been tested or are not fully supported

Backwards compatibility. I have purged my development machine of all older development environments, including VB6. Therefore, I haven't tested it on anything older than the .NET 2.0 Framework.

I was able to register to the component using Regasm.exe, view it in OLE Viewer, but none of the classes had methods. I haven't needed to do COM\.NET integration since 2002, so I'm sure there is something small I have forgotten, but didn't feel this was a priority.

If you need to port it to the 1.0 framework:

You will have to use an older solution file, or manually edit the solution using a text editor.

Collapse the SysConfiguration into a single class instead of using a partial class.

Use the legacy classes instead of the 2.0 System.Configuration namespace.

Inheritance. Unfortunately, it is hard to make to make the Singleton design pattern inheritable, without some sort of hack, such as the base class knowing of the super class. It is unfortunate, because I can think of many scenarios where SysConfiguration could be a good base class. My best compromise to this was to break up the Singleton and configuration functionality using partial classes.

C# only. It was enough work building this once. I didn't have time to create it in VB.NET as well.

Centralized configuration data. Some third party configuration managers have a central location for configuration data, that all local and remote processes access. I've never liked this architecture because you have so many cross process\network calls. If you really wanted this, you could load it into Component Services and make all the calls through there, but you will get a performance hit.

No user interface for editing configuration. I don't find that much value in the user interface provided by the Enterprise Library, and I usually edit my configurations with Notepad. Keep in mind that SysConfiguration uses standard XML, validated against a schema, so you can use the XML editor in Visual Studio or any other third party tool. Since the XML is validated against the schema, you should get a warning if you put in an invalid value.

Configuration structural changes require recompilation. As I mentioned before, you cannot change the structure of the configuration without recompiling. This is because of the strongly typed nature of this project. I don't feel this is a deficiency because you would have to change your code to access the new configuration element anyways, but wanted to bring it up. Obviously, you can change the configuration data without recompilation, just not the structure.

Editing configuration. There is no built-in support for editing configuration data. There are probably reasons for doing this, but I've never run across it. If the data is volatile, I will always store it in the database so it can be shared across the server farm. At the end of the day, it's just XML, so you could edit it using the standard XML classes.

No integrated encryption. .NET 2.0 has the ability to encrypt sections of config files. I have not built this functionality in, but can see myself adding it later. For now, use the standard cryptography libraries and do it yourself.

Not CLS compliant. Although my code is CLS compliant, the code generated by XSDObjectGen is not. The generated code is a key item, that I felt it best to mark the entire class as non-CLS compliant.

Automatic file change detection. A nice (or not nice) feature of App.config and Web.config is that it will restart the process if the config file changes, reloading the settings. I have not looked into replicating this feature (or defect, depending on your point of view). I personally think I prefer being able to force the reload manually, but would like to make this an optional feature.

Points of Interest

The following are some comments about the code and development process that may be of interest to some people.

Conclusions about Test Driven Development

The following section describes my opinion of Test Driven Development when compared to the traditional process of developing the code and (maybe) creating automated unit tests. It is not based on any empirical study, and should be treated as opinion, not fact.

I definitely feel that TDD helped me make a much more robust component than using traditional development. It was very good for testing the various architectures quickly and repeatedly. A few times, I made some major refactoring of the architecture, and having a full regression test was invaluable in helping me to get the component functional again.

In terms of whether I actually developed this faster using TDD than traditional development methodologies, I am not sure I agree. Creating and refactoring the unit tests do take time and can't be discounted. The argument is that creating the tests takes less time than debugging the problem. The only way to accurately test this would be to clone a person and have them develop the component under identical conditions but using both techniques, which is just not possible. I do think you would see a much greater return when you have a team larger than a single person, because the scenario of another developer breaking somebody else's code is much more likely in that case.

Some proponents of TDD will say that when tests fail unexpectedly, reverting the code to the last version that passed all tests is almost always more productive than debugging. I have to say, I did spend considerably less time debugging than usual, but don't feel I should have ever rolled back. I think debugging was always the better option, especially considering how good the debugger is in VS2005.

Even though this version was developed by a team of one, I tried to act like I was working in a team. I tried to make sure to only check in the test when the underlying code passed (i.e., green). In theory, this means that if we were using Continuous Integration, it would always pass. The only issue was to fight the urge to check in the test once it was written. I'm used to the mentality of keeping my changes small and check-ins frequent, but you have to change your mentality slightly.

One item of interest is the ratio of lines of code of the unit tests vs. application code.

4887 total lines of code

3401 lines of unit tests

1486 lines of application code

So we end up with an approximate ratio of 2:1 of unit tests to application code. That is higher than typical, although many of the tests are duplicates for different architectures, which would explain the high ratio.

To answer the question of whether I would suggest using TDD on a project, the answer is yes, with caveats. Although you can't tell from this project, I would suggest using TDD for any component that is called by other components. Writing effective unit tests for the web layer is still difficult unless you build in some way to bypass authentication and session data. I definitely feel it creates much more reliable code and makes changes easier due to the extensive regression test it creates.

Quality of Code

Since this is intended to be used and extended by a broad range of people, I tried to:

Use FxCop to clean up some exception handling and other style issues. Many of the exclusions were from the code XSDObjectGen generated, or simply didn't apply to what I was trying to accomplish (e.g., globalization).

I really wanted to use NCover to ensure I had 100% code coverage with my unit tests. This was actually harder than I expected. Many of the tests run in different processes (console, web, COM+, etc.). NCover can't figure out they are all running from the same set of tests, so it showed poor coverage, even though the superset of all the tests would probably be close to 100%.

XSDObjectGen.exe

At one point, instead of using XSDObjectGen.exe, I did try to use XSD.exe to generate my class files, but it suffers from one major deficiency. No support for the <xs:import> tag. This forces you to keep all of your definitions in one file, which is difficult to manage.

I find XSDObjectGen so much better than Strongly Typed Datasets, because they are lighter and you can create deeper hierarchies than row and column. The only issue is that you have to load the data yourself.

Troubleshooting

Problem: System is raising a System.IO.FileNotFoundException.

It cannot find the configuration file or the schema used to validate it. See step 2 of "Adding SysConfiguration".

Problem: The compiler is raising: Could not find a part of the path 'C:\Projects\SysConfiguration\Code\Configuration\Schemas\RightsConfig.xsd'. C:\Projects\SysConfiguration\Code\Configuration\Schemas\Settings.xsd.

xs:import seems to need the absolute path. Edit Settings.xsd to point to the correct location.

Problem: The compiler is raising: Unable to copy file "obj\Debug (With Sample Configuration)\Name.Randar.txUnitTests.dll" to "bin\DebugWSC\Name.Randar.txUnitTests.dll". The process cannot access the file 'bin\DebugWSC\Name.Randar.txUnitTests.dll' because it is being used by another process.

The COM+ component is still running. Open up Component Services, expand COM+ Application, right click on SysConfiguration Unit Tests, and choose "Shut Down".

Conclusion

I wrote the first version of this component in 2002. Since then, it's been rebuilt and refactored many times. At the same time, the overall core design has changed very little and it's weathered the test of time. This latest version and the accompanying article took quite a bit of time to write. You are free to incorporate it into your code, and all I ask is that you don't take credit for my work and to please email me with feedback (both good and bad) if you do use it.

History

July 12, 2007: First revision.

August 8, 2007: Removed the password on the strong name key that is used to sign the assembly.

Share

About the Author

Shipping product and getting teams to work at peak efficiency are my passions. I’m a firm believer in Agile methodologies, proper engineering practices with a focus on Software as a Service (SaaS). My extensive knowledge of technology as well as my passion, loyalty and ability to learn quickly will add value to any company. Many of my duties have included working closely with customers and I am known for being a great communicator of ideas and concepts.

Comments and Discussions

I have to disagree about App.config or Web.config being loosly typed. The AppSettings section is a simple dictionary of keys and values, but this is such a miniscule part of the .NET 2.0 configuration framework. The vast majority of configuration placed in a .config file, if used properly, is not only strongly typed, but also validated, automatically converted, and exposed through a natural object model to code.

AppSettings is a very simple, basic way to add a few settings to your application. If you need to store more than a few simple settings (or mostly non-string settings data), you should be writing custom configuration sections. Take a look at my article series, The Mysteries of .NET 2.0 Configuration, http://www.codeproject.com/dotnet/mysteriesofconfiguration.asp, for a full understanding of what .NET 2.0 configuration is all about. Its MUCH more than AppSettings or weakly typed data. Much, if not all, that you are trying to accomplish with your custom configuration manager can be accomplished with what is already available in the .NET 2.0 configuration framework. It is extremely flexible and powerful.

It has taken me a while to respond to this, but I wanted to try out the tricks you describe in your article on a real project before responding. As you stated, the normal AppSettings, which is what most people use, is not strongly typed. You have to use a custom configuration section to get any typing or validation. This means writing code, that honestly I found fairly cumbersome to write, even with your very thorough article. In comparing the two ways, I feel that the SysConfiguration class is actually much easier to use, with the only disadvantage being that you have to have XSDObjectGen available to developers (i.e. not in production). Here are my conclusion on the custom configuration sections:

Pros (which SysConfiguration does just as well):-If an element is not defined in the configuration section, it will raise an error first time it's loaded as long "IsRequired = true" is set. Although this is done just as well in SysConfiguration using minOccurs=1.-Allows for optional settings. This can be done using IsRequired=false, or minOccurs=0 in SysConfiguration.-If a configuration setting is renamed, it will fail at compile time. Same as in SysConfiguration.-Settings can be typed (e.g. bool, string, etc.)

Cons:-I really don't like how configuration information is stored is attributes instead of elements.

<CustomConfiguration
IsActive="true"
/>

The only way to use elements seems to be to create a differnt <section> for each element, which creates a lot of classes and bloat.

-If you use attributes, you can't comment each attribute since <!- --> is not allowed within the square braces. The following will fail.

<CustomConfiguration
<!-- This specifies whether the system is active -->
IsActive="true"
/>

-Your sample code checks to make sure the section is there, and if not, raises an exception.

I found that if the section was missing, it was a valid object with default values (i.e. nulls, empty strings and false booleans). I tried different ways to catch an invalid App.config, but nothing worked. SysConfiguration does a much better job of handling missing files.

So in conclusion, SysConfiguration was much better than the configuration management in 1.1, and although 2.0 is much better, but I still feel SysConfiguration is easier to use and handles invalid configurations much better.

I am not sure most of your arguments are very valid. For one, regarding attributes/commenting, its a simple matter of doing something like pulling the attributes to the line above in a comment (which is what I do):

(Preferring every single value be stored in an element is certainly something of personal preference, but that makes for more verbose, possibly much more verbose, vocabulary, and could limit your options in terms of hierarchical considerations (collections of data, etc.))

In regards to checking for errors in a configuration section (or determining if it was present in the config file), you have LOADS of metadata to tell you every last ounce of what could have gone wrong (or even if anything went wrong. You have ElementInformation and SectionInformation which can be used to access information such as a list of errors that even contains the filename and line number the error occurred at, whether your code had permission to perform the requested operation on the section or element, whether the configuration information is new, added during runtime, and not yet saved to the underlying .config file, and much, much, much more.

The example code you posted is not a check for whether there were errors in the section...its a check for whether the section was defined (in the configSections element at the top of a .config file), not whether it was valid and parsable. Rather than just simply failing to load your configuration in the event of an error, the .NET 2.0 configuration framework will do its best to load what it can, and provide you with information about what failed. Not only that, you can then programmaticly fix any bad or missing data and resave.

A cursory glance at my article to find reasons why .NET 2.0 configuration isn't up to snuff with your SysConfiguuration thing is certainly a course of action you could take. However, it doesn't change the fact that the .NET 2.0 configuration framework can still accomplish everything you are trying to do, and, as in the case of error handling, I think it is vastly superior.

* Automatically detect if a configuration setting was missing.> Supported natively by .NET 2.0 configuration. Can access ConfigurationElement.ElementInformation to check for errors. Can dynamic cast from ConfigurationManager.GetSection can be done to determin if the section was even defined. Unrecoverable parsing errors will throw an exception. Numerous options exist for checking the validity or existence of a configuration section or setting.

* Works for multiple architectures > This is easy enough to accomplish with externalized config files. You can add a configSource attribute to any configuration section, and put the contents of that section in an external file. Those files can be shared amongst any architecture, and, they exclude the .NET 2.0 specific configuration infrastructure, making them easier to parse from a non-.NET application.

* Strongly Typed Hierarchical Data > This is definitely the case with .NET 2.0 configuration. The only weaky typed section is appSettings, which was never intended for the kind of heavy, improper use it gets these days anyway. Creating a custom configuration section is actually VERY easy, and requires a minimal amount of code. If you hate typing, a simple C# or VB.NET code file template and a few snippets can be created to allow you go codegen most of your configuration sections and their elements (I can create a fairly complex, hierarchical, configuration structure with quite a few settings in about 10 minutes using my own wizards/templates and snippets).

* Standardized configuration entries > Same as with multiple architectures, its very easy to externalize parts of a .config file into multiple, simpler .config files that are easily shared amongst environments and portable with a component.

* Singleton Access> Supported natively by the .NET 2.0 configuration framework: ConfigurationManager. In a web environment, WebConfigurationManager provides additional capabilities, but ultimately calls ConfigurationManager for most operations, meaning ConfigurationManager may be used in a web environment without issue.

1) Requires a third-party tool, XSDObjectGen.exe, to be able to creat configuration. Not required with .NET 2.0 configuration.

2) Lack of inheritance. A .NET 2.0 configuration sections, collections, and elements are ALL inheritable, allowing existing configuration code to be easily reused and extended, again minimizing the work required to actually create these objects.

3) No visual editors. Surprisingly as it may seem, there are actually several visual editors for rapidly creating strongly typed configuration data in Visual Studio 2005. You can graphically configure most ASP.NET settings. It is also possible to visually create strong-typed configuration data for any project, which is stored in a special configuration section that can be added to an App.config or Web.config file. This section can be externalized with configSource, allowing portability.

4) Lack of encryption. The .NET 2.0 framework provides a flexible framework with which you can encrypt your configuration, either by using ready-made encryption classes, or by writing your own if you need more security than is provided by default. This is an important factor these days, with things like ecommerce credit processing keys, database connection strings, and other sensitive data being stored in configuration files.

5) No automatic file change detection (and configuration thereof). The .NET 2.0 framework not only has the ability to detect changes in a .config file...it provides some fairly extensive features that allow you to finly tune when those changes force a reload...or not. You also have several features that allow you to force reloads in code if there have been changes on disk, on your own schedule.

Ultimately, your free to write your own configuration framework if you so wish. In the long run though, I think writing a new framework (and making it as flexible and capable as the .NET 2.0 configuration framework is to start with) is a lot more effort than, say, writing a ConfigurationSection. My point was that the .NET 2.0 configuration framework accomplishes everything it seems you set out to do. Lack of knowledge of something doesn't mean that something doesn't do what you need it to do. The drawbacks listed above, some of which can be very important, do not exist with the .NET 2.0 configuration framework.