Using Generics For Custom Providers To Reduce Code Duplication

0 comments suggest edit

Here is a quick little nugget for you custom provider implementers. I recently scanned through this article on MSDN that describes how to implement a custom provider and found some areas for improvement.

Reading the section Loading and Initializing Custom Providers I soon encountered a bad smell. No, it was not my upper lip, but rather a code smell. Following the samples when implementing custom providers would lead to a lot of duplicate code.

It seemed to me that much of that code is very generic. Did I just say generics?

Simone (blog in Italian), a Subtext developer, recently refactored all our Providers to inherit from the Microsoft ProviderBase class.

One of the first things he did was to create a generic provider collection:

using System;
using System.Configuration.Provider;

public class GenericProviderCollection<T> 
    : ProviderCollection 
    where T : System.Configuration.Provider.ProviderBase
{

    public new T this[string name]
    {
        get { return (T)base[name]; }
    }

    public override void Add(ProviderBase provider)
    {
        if (provider == null)
            throw new ArgumentNullException("provider");

        if (!(provider is T))
            throw new ArgumentException
                ("Invalid provider type", "provider");

        base.Add(provider);
    }
}

That relatively small bit of code should keep you from having to write a bunch of cookie cutter provider collections. But there is more that can be done. Take a look at the LoadProviders in Listing 6 of that article.

There are two things that bother me about that method listing. First is the unnecessary double check locking, which Richter poo poos in his book CLR via C#. The second is the fact that this method is begging for code re-use. I created a static helper class with the following method to encapsulate this logic (apologies for the weird formatting. I want it to fit width-wise):

/// <summary>
/// Helper method for populating a provider collection 
/// from a Provider section handler.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static GenericProviderCollection<T> 
        LoadProviders<T>(string sectionName, out T provider) 
            where T : ProviderBase
{
    // Get a reference to the provider section
    ProviderSectionHandler section = 
        (ProviderSectionHandler)WebConfigurationManager
              .GetSection(sectionName);

    // Load registered providers and point _provider
    // to the default provider
    GenericProviderCollection<T> providers = new 
          GenericProviderCollection<T>();
    ProvidersHelper.InstantiateProviders
          (section.Providers, providers, typeof(T));

    provider = providers[section.DefaultProvider];
    if (provider == null)
        throw new ProviderException(
            string.Format(
                  "Unable to load default '{0}' provider", 
                        sectionName));
    
    return providers;
}

This method returns a collection of providers for the specified section name. It also returns the default provider via an out parameter. So now, within my custom provider class, I can let the static constructor instantiate the provider collection and set the default provider in one fell swoop like so:

public abstract class SearchProvider : ProviderBase
{
    private static SearchProvider provider = null;
    private static GenericProviderCollection<SearchProvider> 
       providers = ProviderHelper.LoadProviders<SearchProvider>
           ("SearchProvider", out provider);
}

By employing the power of generics, writing new custom providers with a minimal amount of code is a snap. Hope you find this code helpful.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

5 responses

  1. Avatar for Simone Chiaretta
    Simone Chiaretta July 13th, 2006

    As always, you find creative way to improve ST code: it's a pleasure working with you on that project.

  2. Avatar for Christopher Steen
    Christopher Steen July 14th, 2006

    A better PROMPT for CMD.EXE or Cool Prompt Environment

    Variables and a nice transparent multi-prompt...

  3. Avatar for Mike
    Mike September 18th, 2006

    Google preved rodnoy!
    apcservicder

  4. Avatar for mat roberts
    mat roberts November 5th, 2006

    dear haacked,
    why would your top lip smell?
    mat

  5. Avatar for Haacked
    Haacked November 5th, 2006

    Mat, it's an old juvenile joke. When someone says, "What's that smell", someone else would say, "Maybe it's your upper lip."
    The general point being that the person asking smells bad, and his upper lip is closest to his nose.