Example: Design-Time Configuration


Chapter 1 showed how the metaconfiguration data for the DatabaseStorageProvider can be manually entered and modified in the application domain configuration file. While it is entirely possible to take this route for all of the configuration data for an application, you should avoid it when at all possible. Entering and editing configuration data with an XML editor requires detailed knowledge of the particular configuration's schema, and there is no way to automatically validate the settings until runtime. A better route to go is using a tool like the Enterprise Library Configuration Tool to modify, validate, and save configuration information.

This chapter has shown how to use the Enterprise Library Configuration Tool to configure the runtime features in the Configuration Application Block. It has also detailed the architecture behind the design-time features in the Configuration Application Block and promoted how such features allow for great extensibility in the entire design-time experience. This example proves that point. This section walks through the tasks that are involved in adding design support and extending the Enterprise Library Configuration Tool by adding design-time features for the DatabaseStorageProvider.

As previously mentioned, a configuration node encapsulates a group of logically related runtime configuration settings for display and modification at design time. When you select a configuration node, the Enterprise Library Configuration Tool displays the properties associated with that configuration node in the Property pane. The configuration node's properties are the most granular level at which configuration settings can be altered.

The first task for extending the design-time experience of the Enterprise Library Configuration Tool is to create a project that will contain the classes that represents the new ConfigurationNode and ConfigurationDesignManager. Some thought must be given to determine which configuration node settings should be exposed. You expose the settings of a configuration node by creating the configuration node with public properties to reflect the values stored in its associated runtime configuration object. The DatabaseStorageProviderNode contains the following public properties: Name, DatabaseInstance, GetConfigStoredProcedure, SetConfigStoredProcedure, TypeName, and DatabaseStorageProviderData.

  • Name. Because the public Name property is defined in the base ConfigurationNode class, it does not need to be redefined. This property represents the name of the node that is displayed in the configuration hierarchy. Because it is a public property, it is also displayed in the Property pane of the Enterprise Library Configuration Tool.

  • DatabaseInstance. This example requires that the DatabaseInstance property contain data by attributing it as [Required]. This property is especially interesting because I am referencing a ConfigurationNode in the Data Access Application Block through the LinkNodeService (described earlier in the discussion of the services that the ConfigurationDesignHost initializes).

    To indicate which type of node I am referencing, I have attributed this property with the [ReferenceType(typeof(InstanceNode))] attribute. I have also specified the [Editor] and [BaseType] attributes. The Editor attribute allows a special editor to be used in the Property pane for this property. In this case, the ReferenceEditor is being used to make it easier to ensure that users add references to other InstanceNodes that already exist in the application's configuration. The ILinkNodeService provides the ability to create the reference to another ConfigurationNode.

  • GetConfigStoredProcedure. This example uses the GetConfigStoredProcedure property to set and get the name of the stored procedure that will retrieve configuration information. I am requiring that this property contain data by attributing it as [Required]. If no value is set for this property, the configuration settings will fail validation and an error will display in the Enterprise Library Configuration Tool's Configuration Errors window.

  • SetConfigStoredProcedure. This example uses the SetConfigStoredProcedure property to set and get the name of the stored procedure that will save configuration information. I am requiring that this property contain data by attributing it as [Required].

  • TypeName. I am exposing the TypeName property with the [ReadOnly] attribute so users will be able to see the fully qualified type name for this ConfigurationNode but will not be able to edit its value.

  • DatabaseStorageProviderData. The DatabaseStorageProviderData class contains a property for accessing the runtime DatabaseStorageProviderData object. However, since I don't want end users to be able to view this property, I am preventing it from being displayed in the Enterprise Library Configuration Tool by attributing it with [Browsable(false)]. All of the other properties just discussed set the properties of their corresponding runtime counterparts; that is, the DatabaseStorageProviderData class that was created in the last chapter.

Listing 2.5 includes the code for creating the DatabaseInstance property for the DatabaseStorageProviderNode class. The full source code is on the book's Web site.

Listing 2.5. DatabaseStorageProviderNode Class

[C#] [ServiceDependency(typeof(ILinkNodeService))] [ServiceDependency(typeof(IXmlIncludeTypeService))] [ServiceDependency(typeof(INodeCreationService))] public class DatabaseStorageProviderNode : StorageProviderNode {    private InstanceNode instanceNode;    private ConfigurationNodeChangedEventHandler                onInstanceNodeRemoved;    private ConfigurationNodeChangedEventHandler                onInstanceNodeRenamed;    private DatabaseStorageProviderData databaseStorageProviderData; ...     [Required]     [Editor(typeof(ReferenceEditor), typeof(UITypeEditor))]     [ReferenceType(typeof(InstanceNode))]     [SRCategory(SR.Keys.CategoryGeneral)]    public InstanceNode DatabaseInstance    {        get { return instanceNode; }        set        {           ILinkNodeService service =               GetService(typeof(ILinkNodeService))               as ILinkNodeService;            instanceNode = service.CreateReference                 (instanceNode, value, onInstanceNodeRemoved,                    onInstanceNodeRenamed) as InstanceNode;            this.databaseStorageProviderData.DatabaseInstance =                String.Empty;            if (instanceNode != null)            {                this.databaseStorageProviderData.DatabaseInstance =                    instanceNode.Name;            }        }    } ... } [Visual Basic] <ServiceDependency(GetType(ILinkNodeService)),_ ServiceDependency(GetType(IXmlIncludeTypeService)),_ ServiceDependency(GetType(INodeCreationService))> _ Public Class DatabaseStorageProviderNode : Inherits StorageProviderNode    Private instanceNode As InstanceNode    Private onInstanceNodeRemoved As _                ConfigurationNodeChangedEventHandler    Private onInstanceNodeRenamed As _                ConfigurationNodeChangedEventHandler    Private databaseStorageProviderData As _                DatabaseStorageProviderData ...    <Required, Editor(GetType(ReferenceEditor), _        GetType(UITypeEditor)), ReferenceType(GetType(InstanceNode)),_        SRCategory(SR.Keys.CategoryGeneral)> _    Public Property DatabaseInstance() As InstanceNode        Get            Return instanceNode        End Get        Set            Dim service As ILinkNodeService = _                    GetService(GetType(ILinkNodeService))            Dim ILinkNodeService As as instanceNode = _                    IIf(TypeOf service.CreateReference _                    (instanceNode, Value, onInstanceNodeRemoved, _                    onInstanceNodeRenamed) Is InstanceNode, _                    CType(service.CreateReference (instanceNode, _                    Value, onInstanceNodeRemoved, _                    onInstanceNodeRenamed), InstanceNode), _                    CType(Nothing, InstanceNode))            Me.databaseStorageProviderData.DatabaseInstance = _                    String.Empty            If Not instanceNode Is Nothing Then                databaseStorageProviderData.DatabaseInstance _                    = instanceNode.Name            End If        End Set    End Property ...  End Class

Since I am creating a new assembly, a new class that implements the IConfigurationDesignManager interface is needed to properly register, open, and save the configuration information for the DatabaseStorageProviderNode. If I were adding a ConfigurationNode to an assembly that already exists, I would modify the ConfigurationDesignManager that already exists instead of creating a new one. The ConfigurationDesignManager is primarily needed to register the new ConfigurationNode and associate menu items and commands with it.

An XmlIncludeType also needs to be added so the Configuration Application Block knows how to create the DatabaseStorageProviderData type. Because the Configuration Application Block uses the service model provided by the System.ComponentModel namespace, I can simply request the XmlIncludeTypeService to accomplish this. In fact, because requesting the services outlined in Table 2.3 is such a common activity, the Configuration Application Block provides a ServiceHelper utility class to make requesting these services easier. In the code for the ConfigurationDesignManager's Register method, shown in Listing 2.6, I use the ServiceHelper class to request both the NodeCreationService and the XmlIncludeTypeService. The full source code for this assembly is on the book's Web site.

Listing 2.6. Register Method for the ExtensionsConfigurationDesign-Manager

  [C#] INodeCreationService service =            ServiceHelper.GetNodeCreationService(serviceProvider); nodetype = typeof(DatabaseStorageProviderNode); service.AddNodeCreationEntry(            NodeCreationEntry.CreateNodeCreationEntryNoMultiples(            new AddChildNodeCommand(serviceProvider, nodetype),            nodetype, typeof(DatabaseStorageProviderData),            SR.DbStorageProviderNodeMenuName)); IXmlIncludeTypeService includeTypeService =            ServiceHelper.GetXmlIncludeTypeService(serviceProvider); includeTypeService.AddXmlIncludeType(            ConfigurationSettings.SectionName,            typeof(DatabaseStorageProviderData)); [Visual Basic] Dim service As INodeCreationService = _            ServiceHelper.GetNodeCreationService(serviceProvider) Dim nodetype = GetType(DatabaseStorageProviderNode) service.AddNodeCreationEntry(_            NodeCreationEntry.CreateNodeCreationEntryNoMultiples( _            New AddChildNodeCommand(serviceProvider, nodetype), _            nodetype, GetType(DatabaseStorageProviderData), _            SR.DbStorageProviderNodeMenuName)) Dim includeTypeService As IXmlIncludeTypeService = _            ServiceHelper.GetXmlIncludeTypeService(serviceProvider) includeTypeService.AddXmlIncludeType(_            ConfigurationSettings.SectionName, _            GetType(DatabaseStorageProviderData))

Finally, a new assembly attribute needs to be added to the AssemblyInfo.cs (or vb) file, because the Enterprise Library Configuration Tool will look for a value for this attribute to determine whether it should load an included ConfigurationDesignManager. Listing 2.7 shows adding the ConfigurationDesignManagerAttribute to the AssemblyInfo file for a ConfigurationDesignManager named ExtensionsConfigurationDesignManager.

Listing 2.7. Assembly Attribute Needed to Recognize ExtensionsConfigurationDesignManager

[C#] [assembly :     ConfigurationDesignManager(     typeof(ExtensionsConfigurationDesignManager)) ] [Visual Basic] <assembly : _     ConfigurationDesignManager( _     GetType(ExtensionsConfigurationDesignManager)) >

Once this assembly has been compiled and deployed so the Enterprise Library Configuration Tool can access it (e.g., copy this assembly to the same directory as the tool), a DatabaseStorageProvider can be added and used as easily as any of the StorageProviders that ship with Enterprise Library's Configuration Application Block. Figure 2.25 shows how I have modified a configuration section by removing the XmlFileStorageProvider and adding a new DatabaseStorageProvider.

Figure 2.25. DatabaseStorageProvider Configuration Node


Thus, the design-time experience provided by the Configuration Application Block and the Enterprise Library Configuration Tool has been extended without modifying any of the code that ships with Enterprise Library. A separate assembly was created that was able to be used to dynamically add new capabilities to the Enterprise Library Configuration Tool. The experience for using this new functionality is no different than using any of the application blocks that ship with Enterprise Library. In fact, as you will see in later chapters, each application block uses the same process that I have just outlined to add its own unique features to the Configuration Tool.




Fenster Effective Use of Microsoft Enterprise Library(c) Building Blocks for Creating Enterprise Applications and Services 2006
Effective Use of Microsoft Enterprise Library: Building Blocks for Creating Enterprise Applications and Services
ISBN: 0321334213
EAN: 2147483647
Year: 2004
Pages: 103
Authors: Len Fenster

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net