There are many uses for providers with accessing a data store being one of the most common.  I'm not going to talk about why to use providers, I am going to address how to use generics and interfaces with providers to make using them a bit easier.

For this series we are going to use a "ContactInformation" object with a few sub-classes, "HomePhoneNumber" and "EmailAddress".

using System;
using System.Collections.Generic;
using System.Text;
using ObjectHelpDesk.DataAccess;
using System.Security.Principal;

    public abstract class PhoneNumber : ContactInformation
    {
        private string _number;
        public string Number
        {
            get
            {
                return _number;
            }
            set
            {
                _number = value;
            }
        }
    }

    public class HomePhoneNumber : PhoneNumber
    {
        public HomePhoneNumber()
        {
            Name = "Home Phone";
        }
    }

    public class EmailAddress : ContactInformation
    {
        public EmailAddress()
        {
            Name = "Email Address";
        }
        private string _address;
        public string Address
        {
            get
            {
                return _address;
            }
            set
            {
                _address = value;
            }
        }
    }
public abstract class ContactInformation : IReadDataObject<ContactInformation,Int32>
    {
        private String _name;
        public String Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }     
    }

One thing I have noticed is that most providers use the same basic Configuration Section, the section has a list of providers, the default provider and nothing else; so let's look at that code first.

using System.Configuration;

namespace ObjectHelpDesk.DataAccess
{
    public class ProviderConfigurationSection : ConfigurationSection   
    {
        [ConfigurationProperty("providers")]   
        public ProviderSettingsCollection Providers   
        {   
            get  
            {   
                return (ProviderSettingsCollection)base["providers"];   
            }   
        }   
  
        [ConfigurationProperty("default", DefaultValue = "default")]   
        public string Default   
        {   
            get  
            {   
                return (string)base["default"];   
            }   
            set  
            {   
                base["default"] = value;   
            }   
        }  
    }
}

In the web.config you would tie the code to a section by adding a line to the configSections and create the section as well. 

<configuration>
    <configSections>
    ...
        <section name="ContactInformationProvider" type ="ObjectHelpDesk.DataAccess.ProviderConfigurationSection"/>
    </configSections>
    ...
    <ContactInformationProvider default="dummy">
        <providers>
          <add name="dummy" type="DummyProviders.dummyContactInformationProvider,DummyProviders"/>
        </providers>
    </ContactInformationProvider>

Where does the ContactInformationProvider section name come from? it is set by ...<section name="ContactInformationProvider"... But that is only part of it, there is another part in the code; we will get to that a little later.

Next we have two classes, ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType> and ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType, ProviderConfigurationSectionType>.

ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType> is defined as follows

public class ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType> : ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType, ProviderConfigurationSection>
        where ProviderCollectionType : ProviderCollection, new()
        where ProviderType : ProviderBase
    {
        public ProvidersRepositoryGeneric() : base()
        {

        }
    }

The class has very little to it, in fact it inherits the other class ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType, ProviderConfigurationSectionType>.  Why did I do this?  I do not expect to use a different ProviderConfigurationSection class very often and I would rather only have to set two types in my generics.  There are couple of things that are interesting about this class...

The other class ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType, ProviderConfigurationSectionType> has a bit more to it...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration.Provider;
using System.Configuration;
using System.Web.Configuration;

namespace ObjectHelpDesk.DataAccess.Generics
{
    public class ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType, ProviderConfigurationSectionType>
        where ProviderCollectionType : ProviderCollection,new()
        where ProviderType : ProviderBase
        where ProviderConfigurationSectionType : ProviderConfigurationSection
    {
        public ProvidersRepositoryGeneric()
        {
            LoadProviders();
        }
        private ProviderCollectionType _providers = null;
        private ProviderType _provider = null;

        private void LoadProviders()
        {
            //if the provider is set someone beat us here and bail.
            if (_provider == null)
            {
                //make an object to lock the method/objects with.
                Object processLock = new Object();
                lock (processLock)
                {
                    //ok someone else could have been waiting and hit this once the lock cleared
                    //so lets make sure the provider hasnt already been set and skip this if it has.
                    if (_provider == null)
                    {

                        ProviderConfigurationSectionType configuration =
                            (ProviderConfigurationSectionType)
                            ConfigurationManager.GetSection(SectionName);

                        if (configuration == null)
                            throw new ConfigurationErrorsException
                                (SectionName + " configuration section is not set correctly.");

                        _providers = new ProviderCollectionType();

                        ProvidersHelper.InstantiateProviders(configuration.Providers
                            , _providers, typeof(ProviderType));

                        _providers.SetReadOnly();

                        _provider = (ProviderType)_providers[configuration.Default];

                        if (_provider == null)
                            throw new ProviderException("The Default Provider was not configured");
                        ReadCustomConfigurationSettings(configuration);
                    }//if _provider null inner check
                }//end of lock
            }//_if provider null

        }
        protected virtual void ReadCustomConfigurationSettings(ProviderConfigurationSectionType configuration)
        {
        }
public ProviderCollectionType Providers { get { if (_providers == null) LoadProviders(); return _providers; } } public ProviderType Provider { get { if (_provider == null) LoadProviders(); return _provider; } } private String _sectionName = ""; private string SectionName { get { if (String.IsNullOrEmpty(_sectionName)) _sectionName = typeof(ProviderType).Name; return _sectionName; } } } }

Right away we see the where clauses on the generics are the same except there is a new one "where ProviderConfigurationSectionType : ProviderConfigurationSection".  This restricts the type passed in as ProviderConfigurationSectionType  to the class ProviderConfigurationSection and/or it's sub-classes.

The class has two methods, LoadProviders, which is called from the constructor, and ReadCustomConfigurationSettings, which is called by LoadProviders .

We have several fields that have public accessors.  Each accessor is checking the field for a value and if it is not set it is calling LoadProviders or setting the field.  Why call LoadProviders when it is called in the constructor?  Catastrophic memory failure, or worse forced garbage collection from low resources (In theory they should not be picked up by GC without the containing object being nuked.)  Notice the private property SectionName?  There is no real reason that it is private, but it is that "other part in code" that determines the section name in the web.config.  If you switch it to public add a set accessor you  and remove the LoadProviders call from the constructor you can change the section name you want to read from in code. 

The LoadProviders method reads the providers out of the config section, if I was going use a custom ProviderConfigurationSection I would make a subclass of the  class and override the ReadCustomConfigurationSettings method to read the custom settings.  Simply put, LoadProviders creates a collection of Providers, reads the configuration section and creates the providers.  The line "_providers = new ProviderCollectionType();" creates the empty collection, it is also the reason for the new() where clause in the class declaration.  These classes can be used for a nice little provider model without interfaces. 

With 4 interfaces we can have a nice Provider model for CRUD (Create, Read, Update, Delete).  However, you can also break that into four sets of interfaces allowing a great deal of flexibility. If create, read, update and delete each had their own interface you could implement Create and read to make a log system that you can read from and create new entries but not update or delete.  In most cases that kind flexibility might be like using a sledge hammer to put a push pin in the wall... 

Next : Generics, Interfaces, Providers and You - Part 2:IDataObject & IProvider