Microsoft Enterprise Library for .NET 2.0: Configuration
The long awaited successor of the Enterprise Library for .NET 2.0 has been released by Microsoft at MSDN. From the configuration perspective the main changes are:
- Configuration Application Block was replaced by the .NET 2.0 System.Configuration classes.
- Usage of ConfigurationSection and ConfigurationElement for ser/deserialization.
- Only the Logging Application Block registers to receive file change notifications.
- Object Builder from the CAB (Composite UI Application Block) is used for Configuration Factories.
- Instrumentation can now be configured and is turned off by default.
Configuration of Enterprise Library Application Blocks
Possible configuration scenarios are:
- All configuration data is in App.config (default).
- App.config references another config file which contains all configuration data.
- No App.config but another config file which is located by other means.
- No config file at all. You can new up the objects directly without the help of ObjectBuilder
If you first want to get your hands dirty with the new System.Configuration mechansim of .NET 2.0 you can find more infos here. This article describes how to read/write your App.Config and store complex object graphs (e.g. type safe collections) inside your App.config ....
All scenarios except the last one (later post) are described in this article. When you configure your application blocks the default store is the System Configuration Source. With this strategy your App/Web.Config is searched for your configuration settings. You can retrieve configuration values from other config files via the File Configuration Source. Below is an example shown how to refer from your App.Config file to another XML config file which contains common EntLib Application Block settings.
<configuration>
<configSections>
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
</configSections>
<enterpriseLibrary.ConfigurationSource selectedSource="System Configuration Source">
<sources>
<add name="File Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
filePath="c:\Shared.config" />
<add name="System Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
</sources>
</enterpriseLibrary.ConfigurationSource>
</configuration>
Enterprise Library´s famous graphical configuration tool GUI is very similar to its predecessor. Normally you only need to recreate your configuration files with the new config tool and you are done. In your App.Config a config section is created which uses the FileConfigurationSource that refers to the real config file for your application.
How does the System.Configuration mechanism work?
The goal is to allow the de/serialization of strongly typed objects to and from XML using a human readable format. Every App.Config file begins with a <configuration> tag followed by a <configSections> tag. In this section the XML node name and its type responsible for ser/deserialization is stored. The picture below illustrates this.
When you call a Configuration.GetSection("loggingConfiguration") the LoggingSettings type is from the specified assembly loaded. A ConfigurationSection object can contain in its properties standard types like bool, string, ... which are de/serialized as attributes in the sectione.g. Formatters, Name, TracingEnabled (green rectangles) . Complex types must derive from ConfigurationElement which are de/serialized as a new XML nodes (e.g. yellow node TraceListeners collection). The configuration subsystem takes care of the de/serialization of this compact xml representation of your configuration settings. After all types have been reconstructed you can cast the returned ConfigurationSection object to its original type LoggingConfiguration and use it. Since the Configuration system uses caching the returned objects are read only. You have to create a new configuration object if you want to store a changed configuration section.
Retrieval of Config Settings with no App/Web.config
So much for the eye candy with nice GUI and automatic config file generation. An alternative approach without any App/Web.config is possible. This way you don't need to specify the path and file name in n App.config files. Good candiates for common settings are the Exception Handling and Logging Block. The bad news is that to change the configuration Source of this two block you need to replace the static facades by your own ones. Once done you can create your own FileConfigurationSource and point to your global config file. This way you have encapsulated the location and name of a global config file at one central storage location.
LogWriter writer = null;
FileConfigurationSource source = new FileConfigurationSource(@"C:\Shared.config");
factory = new LogWriterFactory(source);
writer = factory.Create();
But wait you don´t need to stop here. Why not get your configuration from somewhere else? The Application Block´s retrieve their configuration via the interface IConfigurationSource. One of the Enterprise Library samples show´s you how to implement a SqlConfigurationSource. Now we can get e.g. the logging settings from a totally different storage location.
SqlConfigurationSource source = new SqlConfigurationSource(
“Connection String“,
“EntLib_GetStoredProcName“,
“Entlib_SetStoredProcName“,
“Entlib_RefreshStoredProcName“,
“Entlib_RemoveStorecProcName“);
factory = new LogWriterFactory(source);
writer = factory.Create();
No Configuration Block anymore
With .NET 2.0 many new features have been introduced, especially the System.Configuration namespace has been significantly enhanced. The ConfigurationMigration Quick Start Sample of the Enterprise Library shows you how to read and write configuration values with no help of the Enterprise Library at all. Reading a ConfigurationSection is easy but writing is a bit more tricky. The reason behind this is that when you call ConfigurationManager.GetSection a read only ConfigurationSection is returned. To save a changed configuration section you actually have to remove the section and then add it again.
using System.Configuration;
// Open App.Config file
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.Sections.Remove("EditorSettings");
config.Sections.Add("EditorSettings", configData);
// Write the new configuration data to the XML file
config.Save();
So when do I need the Enterprise Library?
If you want more than the default System.Configuration System supports. This are
- Register for changes in configuration settings.
- Read/Write Configuration Settings from SQL Server.
- Read/Write arbitrary configuration files.
- Store objects with full type and version info inside Strongly Typed Collections (PolymorphicConfigurationElementCollection).
- Switch from one config file to another one by changing your App.config file
To retrieve your configuration values from the currently configured repository you can use the following code snippet:
// Create SystemConfigurationSource if SystemConfigurationSource is selected
// or a FileConfigurationSource if another config file is referenced in my App.config file
IConfigurationSource selectedConfig = ConfigurationSourceFactory.Create();
// Get Configuration from wherever even SQL Server configuration source is possible
// via this generic interface
ThreedConfigData conf = selectedConfig.GetSection("ThreedConfiguration") as ThreedConfigData;
More info about strongly the strongly typed collection class PolymorphicConfigurationElementCollection can be found here.
You can link with System.Configuration config files together. But it is complicated to read and write arbitrary config files with this mechanism. Luckily the new Enterprise Library helps you out. The code below does exactly the same than the one above: Store some data in an config file.
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
const string CFG_FILE = @"C:\mySettings.config";
FileConfigurationSource source = new FileConfigurationSource(CFG_FILE);
source.Save(CFG_FILE, "MySection", configData);
As you can see configuration has become easier and more flexible with the new Enterprise Library. The work at the Patterns & Practices group shows what can be achieved when quality is the goal number one. Have a look at the new features and the library itself. It is definitely worth it.
Fans of the "old" Enterprise Library can look for configuration tips from from Scott Densmore.
Thats all for today and about time to go to bed (3.26 am GMT+1).