RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Adding Configuration Support for Custom Providers in Enterprise Library in ASP.NET 2.0 : Page 2

By adding configuration design support, you can make your custom providers look and feel just like the built-in providers, letting users select them and provide settings through the Configuration Console.

Determining the Provider Configuration Requirements
First you need to decide what configuration values you need to persist for your provider. These are the attributes that will appear in the element for the provider, excluding the type and name attributes that the configuration system automatically provides through the base classes you will extend. The values will appear as properties in the Configuration Console (from the configuration node classes you create), and be passed to your class constructor at runtime (through the configuration data classes you create).

The example cache backing store provider requires only one property—a String that is the full path to the folder where it will create the cache files—persisted via the path attribute in the configuration file. You're not limited to strings; you can persist any needed value type, and the configuration system will convert it to the correct type at runtime. However, if you need to persist reference types (such as child node types and their values), you must create separate configuration node and configuration data classes for those. For some good examples, take a look at the way that the Caching Application Block and other application blocks provide classes like this in their Configuration and Design subfolders.

Modifying the Custom Provider Class
You need to make only simple modifications to the existing provider class to support the configuration. I've changed the class name to CustomFileBackingStore in the downloadable example code so you can install both the basic custom provider from the previous article and this design-configured provider without naming conflicts. The class that will provide the runtime configuration data is named CustomFileCacheStorageData. You will see details of this class later. The provider class requires a ConfigurationElementType attribute that specifies the configuration data class, which you add to the class definition:

   public class CustomFileBackingStore : BaseBackingStore
The only other change is to the provider class constructor. Now it must accept parameters that are of the correct typed value. In the example, the only parameter required is the path to the cache file folder:

   public CustomFileBackingStore(String cacheFilePath)
      // store the path and filename provided by the parameter
      if (cacheFilePath != String.Empty)
         filePath = cacheFilePath;
         throw new Exception("Error in application configuration, '"
            + filePathConfigurationName + "' attribute not found");
The rest of the code is the same as before. Note that the constructor still checks that there is a value for the path attribute in the configuration file (which appears as the cacheFilePath parameter to the constructor). The Configuration Console will force users to provide this attribute/property, but remember that users may edit the configuration file manually, outside of the console, so you should still check that any required values are present within your constructor.

Creating the Configuration Data and Configuration Node Classes
The provider relies on a configuration data class that exposes the configuration at runtime. Create a new class within the Configuration subfolder of the block you are extending, and add the required namespace references. For the example caching backing store provider, you need these references:

   using System.Configuration;
   using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
   using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.
   using Microsoft.Practices.EnterpriseLibrary.Caching.
   using Microsoft.Practices.ObjectBuilder;
The usual approach is to use this file to hold both the configuration data class and its associated assembler class. The configuration data class carries an Assembler attribute that specifies the assembler class that Object Builder uses to create the configuration data class instance.

Author's Note: ObjectBuilder is a utility that underlies several patterns & practices tools, including the Composite UI Application Block (CAB), the Mobile Client Software Factory (MCSF), and Enterprise Library. ObjectBuilder provides a pipeline that allows code to create or retrieve instances of objects pre-configured to meet the needs of the code, through a series of strategies that take place in stages such as PreCreation, Creation, Initialization, and PostInitialization. An Assembler class you create in your own code uses ObjectBuilder to construct the final object and instantiate it through hard coded values for the object type to create, the constructor requirements of that class, and any extra work required to initialize the object before returning it. For more information on the ObjectBuilder and Assembler classes, see Brian Button's "One Agile Coder" blog.

The next listing shows the configuration data class, which should inherit from a suitable base class such as (in this case) CacheStorageData. It also carries the Assembler attribute that specifies the class CustomFileBackingStoreAssembler. Inside the configuration data class, you must provide a default constructor that takes no parameters, and a constructor that takes the name parameter (the name of the custom provider) and any properties the provider requires. In this example, the only property is the path to the cache file folder:

   namespace Microsoft.Practices.EnterpriseLibrary.Caching.Configuration
      public class CustomFileCacheStorageData : CacheStorageData
         private const string pathNameProperty = "path";
         public CustomFileCacheStorageData()
         public CustomFileCacheStorageData(string name, string pathName)
            : base(name, typeof(CustomFileBackingStore))
            this.CacheFilePath = pathName;
Note that the preceding code saves the provider-specific parameter value in a local variable and exposes it as a public property. The configuration data class must expose the properties of the provider so that the configuration system and the provider can read and set them. For each property, add a ConfigurationProperty attribute that makes that property visible in the Configuration Console, specifies the name of the attribute in the configuration file, and indicates whether the property is optional or required, as shown below:
       [ConfigurationProperty(pathNameProperty, IsRequired = true)]
       public string CacheFilePath
           get { return (string)base[pathNameProperty]; }
           set { base[pathNameProperty] = value; }
The example provider has only one property, named CacheFilePath. In the preceding code, the local variable pathNameProperty holds the attribute name ("path"), which is required. The base class property collection stores the property value, so the property accessor indexes into that collection to retrieve and set the value.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date