C# Programming: Using Generic Factory Classes to Create Generic Exception Handlers

Introduction

Exception handling is termed to be a costly affair and should be used meticulously. It undoubtedly serves as an integral part of our applications, and cannot be sidelined for any reason. The common problem in implementing an Exception handling mechanism is the dependency on the library after we create a provider.This C# tutorial looks at a possibility of switching the providers at ease.

It's a problem for every developer be it ASP.NET developer or C# developer. Evaluating each provider takes some toll on the development. So let us re-use them.

For e.g. If you start using the Enterprise Library, you can't just switch your code if you decide to switch the provider.The solution in such cases is to create wrappers around this common piece and abstract the provider. You can use factory classes like shown below and abstract the provider. Then switch providers through a simple config change.

For reference: this article uses Enterprise Library as default provider. The code sample below consists of a Factory Class that facilitates easy pick of an Exception handler through a config change.

To start with create an interface, as shown below.

List down all the methods that you think any Exception handling component would have. For now, let's start with a single method HandleException which asks for an Exception object and a policy name.

namespace Infrastructure.ExceptionHandling
{
    /// <summary>
    /// IExceptionHandler defines a contract for the Exception Handlers.
    /// </summary>
    public interface IExceptionHandler
    {
        /// <summary>
        /// Handles the specified ex, applying the policy.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="policyName">Name of the policy.</param>
        /// <returns></returns>
        bool HandleException(Exception ex, string policyName);    }
}

Create an Exception handler Factory Class to return an instance of the Exception handler.We need to create as many Exception handlers as we need to switch.The Interface IException handler would drive the exception handlers.

namespace Infrastructure.ExceptionHandling
{
    /// <summary>
    /// creates Exception handler.
    /// </summary>
    /// <typeparam name="TExceptionHandler">The type of the Exception handler.</typeparam>
    public class ExceptionHandlerFactory < TExceptionHandler > where TExceptionHandler: IExceptionHandler, new()
    {
        /// <summary>
        /// creates an instance for TClass
        /// </summary>
        /// <returns>instance of TClass</returns>
        public static TExceptionHandler CreateProvider()
        {
            TExceptionHandler instance = new TExceptionHandler ();
               return instance;
        }
    }
}



C# Programming: Using Generic Factory Classes to Create Generic Exception Handlers

Create a Wrapper

Wrapper is created to make all our calls routed through one common method.

namespace Infrastructure.ExceptionHandling
{
    public static class ExceptionWrapper
    {
        /// <summary>
        /// exceptionHandler
        /// </summary>
        static IExceptionHandler exceptionHandler;

        /// <summary>
        /// Gets the exceptionHandler.
        /// </summary>
        /// <value>The exceptionHandler.</value>
        public static IExceptionHandler ExceptionHandler
        {
            get
            {
                if (null == exceptionHandler)
                {
                    //Create the Exception Handler
                    exceptionHandler = ExceptionHandlerHelper.GetExceptionHandler();
                }
                return exceptionHandler;
            }
        }

    }
}

Create a Helper Class for Exception handler. Please note the use of the Exception handler type. This is what corresponds to multiple exception handlers. Currently Microsoft Enterprise Library is used as an example. We can add as many as need be. Also create a Property in the setting file - ExceptionHandlerType. This Property can be used to switch between the Log Providers. Currently it holds the default value of "ENTLIB".

namespace Infrastructure.Logging
{
    /// <summary>
    /// Enumurator for ExceptionHandlerType
    /// </summary>
    public enum ExceptionHandlerType
    {
        /// <summary>
        /// Microsoft Enterprise Library
        /// </summary>
        ENTLIB
    }


    /// <summary>
    /// Helper class for Exception Handler
    /// </summary>
    public class ExceptionHandlerHelper
    {
        private static  ExceptionHandlerType  _exceptionHandlerType   = ExceptionHandlerType.ENTLIB;
        private static  IExceptionHandler  _exceptionHandler       = null;
        
	
       /// <summary>
        /// Initializes the <see cref="ExceptionHandlerHelper"/> class.
        /// </summary>
        static ExceptionHandlerHelper()
        {
            try
            {
                _exceptionHandlerType = (ExceptionHandlerType)Enum.Parse(typeof(ExceptionHandlerType), 	Properties.Settings.Default.ExceptionHandlerType.Trim().ToUpper());
            }
            catch //(Exception exception)
            {
                //Set the default to EntLib
                _exceptionHandlerType = ExceptionHandlerType.ENTLIB;
            }
        }

        /// <summary>
        /// Gets the Exception Handler.
        /// </summary>
        /// <returns></returns>
        public static IExceptionHandler GetExceptionHandler()
        {
            switch (_exceptionHandlerType)
            {
                case ExceptionHandlerType.ENTLIB:
                    return _exceptionHandler = ExceptionHandlerFactory<EntLibExceptionHandler>.CreateProvider();
                default:
                    return _exceptionHandler = ExceptionHandlerFactory<EntLibExceptionHandler>.CreateProvider();
            }
        }
}

}

And finally, the implementation of the Entlib Exception handling class. Note the use of the local Exception.

#region Namespaces

using Microsoft.Practices.EnterpriseLibrary.Logging;

#endregion Namespaces

namespace Infrastructure.ExceptionHandling
{
    /// <summary>
    /// ExceptionHandler class. Uses Microsoft Enterprise Library
    /// </summary>
    public sealed class EntLibExceptionHandler : IExceptionHandler
    {
        /// <summary>
        /// Handles the specified ex.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="policyName">Name of the policy.</param>
        /// <returns></returns>
        public bool HandleException(System.Exception ex, string policyName)
        {
            return ExceptionPolicy.HandleException(ex, policyName);
        }
    }
}}

    
Don't forget to add the Exception handler configuration in the Application config file
     
<!-- ENTLIB EXCEPTION HANDLING CONFIGURATION START -->

    <section name="exceptionHandling" 	type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, 	Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" />
 	<exceptionHandling>
   	 <exceptionPolicies>
      		<add name="Default Policy">
     		   <exceptionTypes>
         			 <add name="Exception" type="System.Exception, mscorlib" postHandlingAction="None" >
          		  <exceptionHandlers>
            		  <add name="Infrastructure Exception Handler"
               			 type="Infrastructure.ExceptionHandling.InfrastructureExceptionHandler,Infrastructure"/>
             		 <add name="Logging Block"
       		logCategory="Error"
       		 eventId="100"
        		severity="Error"
       		 title="My App"
       		 formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, 		
		Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"
       		 priority="0"
        		type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, 		
	   	Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging"
        	/>
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>
  </exceptionHandling>

  <!-- ENTLIB EXCEPTION HANDLING CONFIGURATION END -->

All in place, we need to handle our exceptions using the exception handler that we created. Note that the switch for the exception handler is made at the provider level and not at the consumer level.

//Create the Exception Handler and handle the exception.
ExceptionWrapper.ExceptionHandler.HandleException(ex, "Default Policy");

Note that since, Entlib uses IExceptionHandler as one of its interfaces. You would have to rename the IExceptionHandler with a different name when you try this code. The name used here is only to make it easy to understand.

Also note that, you may have to read the Exception Handling Application Block documentation to understand about the Exception policies supported by the Enterprise Library.

The ground rule of exception handling would still apply: Do not catch an Exception more than once per thread.

References

http://msdn.microsoft.com/en-us/practices/default.aspx
http://www.microsoft.com/downloads/details.aspx?FamilyId=5A14E870-406B-4F2A-B723-97BA84AE80B5&displaylang=en
http://www.devx.com/dotnet/Article/31463

Related Articles





About the Author

Srinath M S

I would love to leave a footprint in this flat world

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds