Provider pattern is an extremely useful pattern that allows you to write loosely coupled components in .Net framework that can be injected at run time. The concept of provider model is very simple, yet extremely powerful. We create abstraction for our components and define which concrete implementation we want to use in the configuration file. When the code executes, we can create instance of the concrete component mentioned in the configuration file and use that instance to do work.

Using a Provider For Logging

Let’s look at a simple example to understand how providers work in .Net. Let’s say I want to create two separate loggers, one that logs to a file and one that logs to the database. I want to be able to change these loggers very easily based on my needs. If I hard code one of these loggers in code then I cannot easily swap them when I want.

To solve this problem with a provider I will create an interface that will be implemented by both loggers

    public interface ILogger
    {
        void Log(String data);
    }

 Now I need to create logger classes that will implement this interface.

    public class FileLogger : ILogger
    {
        public void Log(String data)
        {
            // Your code to log data to file goes here
            Console.WriteLine("Data Logged to file:" + data);
        }
    }

    public class DatabaseLogger : ILogger
    {
        public void Log(String data)
        {
            // Your code to log data to DB goes here
            Console.WriteLine("Data Logged to Database:" + data);
        }
    }

What is left now is to configure the logger that we want to use in the config file. To do this I simply created a key in config file and defined the fully qualified path of the logger class that I want to use.

  <appSettings>
    <add key="LoggingProvider" value="ProvidersDemo.DatabaseLogger, ProvidersDemo"/>
  </appSettings>

Here ProvidersDemo.DatabaseLogger is the name of the class that I want to use for logging including the namespace and ProvidersDemo is the assembly name.

Once we have defined the provider we can use it in our application:

        static void Main(string[] args)
        {
            // Get the provider name from the config file
            String providerName = ConfigurationManager.AppSettings["LoggingProvider"];

            // Create instance of the provider
            ILogger provider = Activator.CreateInstance(Type.GetType(providerName)) as ILogger;

            // Now we can use the provider
            provider.Log("Some Sample text that we want to log");
        }

 All I am doing in code is to first get the fully qualified name of the logger from config file and create an instance of that class. Our code is using the ILogger abstraction and does not care about the concrete implementation as long as it gets any logger. Once we create instance of the provider we can simply use it to log data.

Now if we want to replace the database logger with file logger in program, all we need to do is change it in the configuration file:

  <appSettings>
    <add key="LoggingProvider" value="ProvidersDemo.FileLogger, ProvidersDemo"/>
  </appSettings>

Now if you run the program again, you will see that our application would have started using the file logger class.

Summary

Providers provide a lot of flexibility and allow us to write extensible code in .Net framework. The concept is rooted from Strategy pattern and is extensively used by .Net framework itself. You might have used ASP.Net Membership providers in the past. Whenever you want to create a plug-able component, you can use providers and they will give you a lot of flexibility.