In this article we will learn the how to use Provider Design Pattern
Introduction
Recently I came across a requirement where there will be two or more providers and based on the configuration value, the concrete providers should act.There should not be any
IF..ELSE block or SWITCH statement to act as the decision maker.Provider Design Pattern is there to rescue.In this case , the concrete providers will sit in the Data Access Layer(DAL) for providing the services.The actual implementation can be decided in the app.config file. In this article we will learn about that.
What is Provider Design Pattern?
Ron Howard mentioned "A provider is simply a contract between an API and the Business Logic/Data Abstraction Layer. The provider is the implementation of the API separate from the API itself".
This pattern which got introduce in dotnet framework 2.0 is use to design components in a decoupled and extensible manner.
Straight to experiment
First we will create a Base Provider.So let us create a class library project and name it as "BaseProvider".The "BaseProvider" library will have the below classes.
- MyBaseProvider:
It is an abstract class that acts as a base for all the concrete providers. This usually contains all abstract methods and properties or overloaded methods and implementation details which can be shared among all providers.This provider class is derived from ProviderBase that provides a base implementation for the extensible provider model.
namespace BaseProvider
{
public abstract class MyBaseProvider : ProviderBase
{
// Gets the text information
public abstract string GetProviderInformation();
}
}
In this case this abstract method "GetProviderInformation()" will return a string information which we will ocme to know later.
- MyBaseProviderCollection:
It takes care of provider configuration.It is derived from ProviderCollection class which represents a collection of provider objects that inherit from System.Configuration.Provider.ProviderBase.
public class MyBaseProviderCollection : ProviderCollection
{
// Return an instance of MyBaseProvider for a specified provider name
new public MyBaseProvider this[string name]
{
get { return (MyBaseProvider)base[name]; }
}
}
- MyBaseProviderConfiguration:
It contains the logic to manage the configuration of the provider.It uses ConfigurationSection as the base class which represents a section within a configuration file.
public class MyBaseProviderConfiguration : ConfigurationSection
{
[ConfigurationProperty("providers")]
public ProviderSettingsCollection Providers
{
get
{
return (ProviderSettingsCollection)base["providers"];
}
}
[ConfigurationProperty("default")]
public string Default
{
get
{
return (string)base["default"];
}
set
{
base["default"] = value;
}
}
}
- MyBaseProviderManager:
This initializes a concrete provider and helps to load user configuration settings in memory
public class MyBaseProviderManager
{
private static MyBaseProvider defaultProvider;
private static MyBaseProviderCollection providers;
static MyBaseProviderManager()
{
Initialize();
}
private static void Initialize()
{
try
{
MyBaseProviderConfiguration configuration = (MyBaseProviderConfiguration)ConfigurationManager.GetSection("ProviderSection");
if (configuration == null)
throw new ConfigurationErrorsException
("ProviderSection configuration section is not set correctly.");
providers = new MyBaseProviderCollection();
ProvidersHelper.InstantiateProviders(configuration.Providers, providers, typeof(MyBaseProvider));
providers.SetReadOnly();
defaultProvider = providers[configuration.Default];
if (defaultProvider == null)
throw new Exception("Default provider not set properly");
}
catch (Exception ex)
{
throw ex;
}
}
public static MyBaseProvider Provider
{
get
{
return defaultProvider;
}
}
public static MyBaseProviderCollection Providers
{
get
{
return providers;
}
}
}
N.B.~The project should have reference to "System.configuration" and "System.Web".

Now comes the part of creating the Concrete Poviders.Create two class library project, name one as "SqlProvider" and the other as "XMLProvider".
Both the projects should have reference to "System.configuration" and "BaseProvider".Now in "SqlProvider" project, create a class say "BaseProvider" that will inherit "MyBaseProvider" and will override the "GetProviderInformation()" method as shown under
using BaseProvider;
namespace SqlProvider
{
public class MySQLProvider : MyBaseProvider
{
public override string GetProviderInformation()
{
return "SQL Provider";
}
}
}
A similar implementation will happen for "XMLProvider" as under
using BaseProvider;
namespace XMLProvider
{
public class MyXMLProvider : MyBaseProvider
{
public override string GetProviderInformation()
{
return "XML Provider";
}
}
}
Now create a console application that will act as the client.In the app.config do the below changes

Kindly note that, based on the "Default" value, the dicision will be made as which provider to use.
And write the below code for invocation
class Program
{
static void Main(string[] args)
{
var result = MyBaseProviderManager.Provider.GetProviderInformation();
Console.WriteLine(result);
Console.ReadKey();
}
}
This project should have reference to "System.configuration","BaseProvider","SqlProvider" and "XMLProvider".

That's it.Let us run the application.And we will receive the below output.

Now change the default value to "XMLProvider" in the config file and here is the output.

Performance
It involves a small amount of reflection at the time of instantiation of the provider object.Once the object is instantiated it is accessed as normal.Object creation via reflection involves a little bit of performance hit but that is negligible.
References
Conclusion
Hope this article will help to understand the easiness of using Provider Pattern.Thanks for reading.Source file is attached.