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 3

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.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Adding an Assembler Class
The assembler class, within the same file, must implement the IAssembler interface, which has a single method named Assemble. Your method implementation will receive a range of variables that the configuration system makes available to the constructor of the concrete implementation of the IAssembler interface within the core Enterprise Library configuration system. The method code casts this to the configuration data type CustomFileCacheStorageData, and then creates an instance of your provider class by calling its constructor and specifying the values for its properties using the values exposed by the configuration data class:

... public class CustomFileBackingStoreAssembler : IAssembler<IBackingStore, CacheStorageData> { public IBackingStore Assemble(IBuilderContext context, CacheStorageData objectConfiguration, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache) { CustomFileCacheStorageData castedObjectConfiguration = (CustomFileCacheStorageData)objectConfiguration; IBackingStore createdObject = new CustomFileBackingStore( castedObjectConfiguration.CacheFilePath); return createdObject; } } }

Author's Note: Probably the easiest way to create your assembler class, depending on the block you are extending, is to copy the assembler class from one of the built-in providers that implements the same provider interface as your custom provider. For example, in this case, the assembler class is adapted from the built-in Isolated Storage provider's configuration data class—CustomFileCacheStorageData.

Building the Configuration Node Class
The Configuration Console uses the configuration node class for your provider to create the node in the configuration tree view, and to present the provider properties to users for editing. Typically, you should create this class within the Configuration\Design subfolder of the block you are extending. However, the Enterprise Library Visual Studio solution that opens from your Start menu contains a separate project for the design features of each application block, and if you're using that solution you should create your configuration node class within the appropriate project.

Next, add the required namespaces to your class. For the example provider, you need the following:

using System.ComponentModel; using System.Drawing.Design; using Microsoft.Practices.EnterpriseLibrary. Configuration.Design.Validation; using Microsoft.Practices.EnterpriseLibrary. Caching.Configuration.Design.Properties; using System; using Microsoft.Practices.EnterpriseLibrary.Configuration.Design; ...

Your configuration node class should inherit from an appropriate storage node base class, as shown in the next listing, depending on the block you are extending. For the example provider, the appropriate base class is CacheStorageNode.

The configuration node class must also expose constructors that allow the Configuration Console to create instances of the class with default property values for new configurations, and with pre-configured values if the user is opening an existing configuration that contains the custom provider. For the example provider, the default constructor calls the constructor of the base class specifying the default name for this node (extracted from the resources file), and an empty string for the CacheFilePath property:

... namespace Microsoft.Practices.EnterpriseLibrary. Caching.Configuration.Design { public class CustomFileCacheStorageNode : CacheStorageNode { private string pathName; public CustomFileCacheStorageNode() : this(new CustomFileCacheStorageData(Resources.DefaultFileCacheNodeName, string.Empty)) { } ...

When a user opens an existing configuration containing this provider, the second constructor takes a reference to the configuration data class containing the existing configuration information, checks that the reference is not null, and sets the Name property of the underlying base class (CacheStorageNode) to the name specified in the configuration. Then it sets all the provider property values using the values specified in the existing configuration—in this case, the path.

... public CustomFileCacheStorageNode( CustomFileCacheStorageData fileCacheStorageData) { if (fileCacheStorageData == null) { throw new ArgumentNullException("CustomFileCacheStorageData"); } Rename(fileCacheStorageData.Name); this.pathName = fileCacheStorageData.CacheFilePath; } ...

The remainder of the configuration node class contains the property accessor for each property configurable in the console, and for the property that exposes the populated configuration data to the provider. You use attributes to specify how the Configuration Console will handle and expose each property that users can configure.

The configuration node class for the example provider has to expose only the CacheFilePath property (again, the Name and Type properties are exposed by the base class). The attributes for this class indicate that the property value is required, and that the Configuration Console should present a SaveFileEditor (a class within the core Enterprise Library configuration that displays a File Save dialog) instance to users when they edit this property. The FilteredFileNameEditor attribute specifies the resource name of a text string in the resources file that the underlying Save File dialog should use as the file type filter ("All files (*.*)|*.*" in this example). Finally, the SRCategory and SRDescription attributes specify string resources that the Configuration Console will display in the status bar and as help text when configuring this property:

... [Required] [Editor(typeof(SaveFileEditor), typeof(UITypeEditor))] [FilteredFileNameEditor(typeof(Resources), "FileCachePathFileDialogFilter")] [SRCategory("CategoryGeneral", typeof(Resources))] [SRDescription("TextAreaNameDescription", typeof(Resources))] public string CacheFilePath { get { return pathName; } set { pathName = System.IO.Path.GetDirectoryName(value); } }

The property accessor itself just retrieves and sets the value of the local class-level variable named pathName. However, one minor issue is that the SaveFileEditor class forces users to specify a file name, and does not allow selection of an empty folder. Therefore, the set clause must strip off the filename that the user selects or enters. You might consider cloning the existing SaveFileEditor class and modifying it to allow selection of a folder, or creating your own more suitable descendant of the UITypeEditor base class, if you require this or more specialized functionality in your custom provider(s).

Finally, you must override the public CacheStorageData property of the CacheStorageNode base class to expose the current instance of the CustomFileCacheStorageData class that contains the configuration information:

public override CacheStorageData CacheStorageData { get { return new CustomFileCacheStorageData(Name, pathName); } } } }

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