Olaf's profile^(?:[^$]*)$ -- Matches e...PhotosBlogLists Tools Help
    February 28

    Third (and last) EntLib hack, gathering requirements

    After writing the ConfigurationConstsWriter and the little ConfigDesigVerbs framework for the EntLib, a colleague of mine challanged me to do a third extension for the EntLib configuration tool.

     

    This third extension should solve the problem op deploying configuration to multiple environments. 

     

    When writing web applications, it is common to have multiple environments (one for development, one for staging or testing and the production environment). The problem is that configuration within these environments should differ, but managing these different configuration files should be done on the development environment.

     

    I’m still pretty much blank on how to solve this problem in the EntLib configuration tool, but accepted the challenge and gathered some requirements:

    1. Editing a configuration file for a specific environment should be done by entering differences only (this also implies a 'default' configuration).
    2. Using the extension should be transparent for the consuming code.
    3. Editing the configuration files should be easy, preferably ‘dummy-proof’.
    4. Any configuration that can be edited in the Configuration tool, can be included.
    5. Storing these configuration files on the development environment should(probably) be done by storing the files for each environment into a different directory.

    Suggestions or requirements? anyone?

     

    Using DesignerVerbs on CofigurationNodes (and testing connection strings) in EntLib

    I’m still having heaps of fun playing around with the Enterprise Library configuration tool. After adding IExtenderProviders here, now it’s the DesignerVerb’s turn.

     

    DesigerVerbs are used to add the hyperlink-like buttons to the PropertyGrid control in the VS.NET design environment. These options trigger commands to accomplish common tasks on a component (or ConfigurationNode).

     

    These DesignerVerbs are usually supplied by class Designers that are specified in an Editor attribute on the ‘class to be designed’. My test case for using DesignerVerbs is on the ConnectionStringNode and does not allow me to specify a Designer (without having to compile my own version of the EntLib dll’s).

     

    Fair enough, first enable support for DesignerVerbs in the configuration tool.
    Second that by making a small framework to load these DesignerVerbs externally.

     

    A quick peek on the result can be found here. Drop the assemblies from the bin folder in the folder that you run the EntLib configuration tool from and start validation your sql-connection strings!

    Enabling DesignerVerb support in the Enterprise Library Configuration tool is done by adding an instance of the IMenuCommandService type to the designerhost. This is done in a similar way as described in this post.

    The solution consists of 3 projects:
    1.) ConfigDesignerVerbs, the assembly that adds DesignerVerb support and loads DesignerVerbs from external assemblies
    2.) ConfigDesignerVerbs.Interface, this assembly should be used by people who would like to write their own Configuration designer verbs.
    3.) ConfigDesignerVerbs.SqlConnectionStringTester, this assembly contains my testcase, a DesginerVerb that tests Sql connection strings agains sql servers.

     

    When the ConfigDesignerVerbs.dll file is dropped in the Enterprise Library configuration tools directory the Configuration tool loads a IConfigurationManager class. In the Register() method of the IConfigurationManager it looks for assemblies that declare the 'ConfigDesignVerbExportAttribute' (from the ConfigDesignerVerbs.Interface dll). Every Assembly that declares this attribute, should pass a Type of IConfigDesignerVerb to the attribute's contructor.

    These types are collected and asked to return a DesignerVerb for a given ConfigurationNode every time a ConfigurationNode has focus in the PropertyGrid.

     

    The ConfigDesignerVerbs.dll, ConfigDesignerVerbs.Interface.dll and the assemblies that export the IConfigDesignerVerbs should be dropped to the Configuration tool's run-directory.

    ==edit==
    You'll have to copy the dll's from the projects bin directory, after recompiling it agains your version of the EntLib dll's


    Download the solution here.

    February 27

    Extending the EntLib Configuration tools inner workings

    The enterprise library configuration tool uses the .net ComponentModel to provide services to the ConfigurationNodes that are designed. This ComponentModel provides components with an IoC-like approach to consume services from their design (or runtime) environment.

     

    This article on theServerSide.net does a good job on explaining these concepts, so I wont bother even to try.

     

    From the services that are used within the VS.NET IDE (and the PropertyGrid) only a couple are provided to the ServiceProvider by the Configuration tooling designerhost.
    Support for IExtenderProviders and DesignerVerbs is missing…

     

    Luckily, the makers of the Configuration tool added a service called IServiceContainer. This service can be used to add services to the environment’s runtime, the same runtime that is shared by the PropertyGrid :).

     

    To add a service to the ServiceContainer, consider the following code:

    IExtenderProviderService extenderProviderService = (IExtenderProviderService) serviceProvider.GetService(typeof(IExtenderProviderService));
    if (extenderProviderService == null)
    {
     extenderProviderService = new ExtenderService();
     svcContainer.AddService(typeof(IExtenderProviderService), extenderProviderService);
     svcContainer.AddService(typeof(IExtenderListService), extenderProviderService);
    }

     

    For the ConfigurationConstsWriter I’ve put this code in the Register method of the IConfigurationDesignManager. The code checks whether a IExtenderProviderService already has been added and if it hasn’t adds its own implemenetation.

     

    If the PropertyGrid loads an object, it checks the IServiceContainer for an IExtenderProviderService. Normally this call would have failed, no one is keeping track of the IExtenderProviders in the config tool. After having added our custom implementation on the interface it displays the extended properties.

     

    As I’m still playing around with the Enterprise Library configuration tool, I’ll be posting a DesignerVerb that allows you to validate a Sql ConnectionString from your configuration tool against a runnning server soon. Using DesignerVerbs requires the PropertyGrid to have access to a service called IMenuCommandService, which will be added in a similar matter to the tool’s runtime.


    The ExtenderService I use is a really straight forward implementation of the IExtenderProvider interface, you can see here:

     public class ExtenderService : IExtenderListService, IExtenderProviderService
     {
      ArrayList extenderProviders = new ArrayList();
      
      #region System.ComponentModel.Design.IExtenderListService interface implementation
      public IExtenderProvider[] GetExtenderProviders()
      {
       IExtenderProvider[] extenderProvidersArray = new IExtenderProvider[extenderProviders.Count];
       extenderProviders.CopyTo(extenderProvidersArray, 0);
       return extenderProvidersArray;
      }
      #endregion
      
      #region System.ComponentModel.Design.IExtenderProviderService interface implementation
      public void RemoveExtenderProvider(System.ComponentModel.IExtenderProvider provider)
      {
       extenderProviders.Remove(provider);
      }
      
      public void AddExtenderProvider(System.ComponentModel.IExtenderProvider provider)
      {
       extenderProviders.Add(provider);
      }
      #endregion
     }


    IoC rocks!

    February 25

    Fixing the Configuration Consts Writer

    I'll confess I got carried away with technology rather than functionality when posting the first version of the Configuration Consts Writer. Shaun C pointed out that the generated code should contain static members, instead of instance members.

     

    This flaw is fixed in the version you’ll find here.
    Here is an updated version of the source.

     

    I did try to generate 'readonly static' fields using System.CodeDom. But after not succeeding without resorting to a CodeSnippetTypeMember I chose to mark the members as plain 'static'.


     

    February 24

    Maintaining constants for EntLib configuration nodes

    Are you maintaining code with constants to compile-time check the names of configuration nodes from the EntLib configuration tool? Try adding this configuration node to your applications configuration!

     

    I could think of a discussion whether maintaining such a file with constants is useful…

    All configuration nodes you use in your applications configuration already have names you can reference them with from your application using string literals. Once chosen the names of configuration nodes, these are unlikely to change. Some might even say that depending on intellisense is wrong.

    On the other hand I know developers who ‘live by’ type safety, being able to intellisense and indirections.

    In my opinion: Intellisense equals ease of use, indirections can be useful (but aren’t a guaranteed recipe for success) and having classes to intellisense your way into a sql-statement is complete bogus.

    After having said that, I’ll present you my ‘Configuration constants writer’ for the EntLib configuration tool.

     


    The configuration consts writer is a configuration node you can add to your applications configuration automatically manage code files containing configuration node names. By Implementing the IExtenderProvider interface (from the System.ComponentModel namespace) it decorates the nodes within your application with a new property: ‘constant name’.

    The ‘constant name’ property will be written to a  code file as a string constant that contains the value of the ‘name’ property of the node the ‘constant name’  was supplied to. The file containing the code is regenerated every time you save the configuration to disk.

    Besides this core functionality it is possible to group the constant declarations in nested classes using a period in your constant name. The configuration consts writer uses System.CodeDom to generate the code file and supports either C# of VB.NET code generation.

     


    Consider the following example:
    In your configuration you define 3 exception policies: “UI Exceptions”, “Service Exceptions” and “Database Exceptions”. You provide theses exception with Constant names called “ExceptionPolicies.UI”, “ExceptionPolicies.Services” and “ExceptionPolicies.Database”.

    Saving the configuration on this application will generate a code file that looks like:
    //--------------------------------------------------------------
    // <autogenerated/>
    //--------------------------------------------------------------

    public class Constants {
        private Constants() {
        }

        public class ExceptionPolicies {
            public const string Database = "database exceptions";
            public const string UI = "UI exceptions";
            public const string Services = "Service  exceptions";

            private ExceptionPolicies() {
            }
        }
    }


     

    Download the binary here.
    Download the sources here.

    And hooray's to the EntLib team for sticking with the System.ComponentModel namespace within their configuration tooling!