About Me

Please see my LinkedIn profile for more information about me (http://www.linkedin.com/in/kevinwhitemmlsolutions).

Wednesday, January 7, 2009

Generic implementation of the Singleton design pattern in C#

I am presently creating a library of reusable code and have several service classes that would be appropiatly implemented as singletons. However rather than implementing the singleton pattern on a class by class basis I wanted a way of reusing a generic class that would allow me to make any class a singleton. Generics and reflection allow this to be achieved in .NET.

The Design
The following fragment of a UML static diagram shows the design of Singleton class.


Points of note:
  • Generic class with parameter T
  • Instance is referenced by the static generic member singletonInstance
  • The static method GetInstance returns the singleton instance or constructs an instance if one has not already been instantiated (lazy instantiation)
  • The static Reinitialize method simply sets the singleton reference to null and invokes GerInstance (causing the state to be reset which could be important for some types of singletons)
  • The methods GetInstance and Reinitialize use the lock statement to ensure thread-safety
The Code

/// <summary>
/// Provides an implementation of the Singleton design pattern. This can be used
/// for resource type objects such as exception handlers.
/// </summary>
/// <typeparam name="T">The type that inherits and hence implements the Singleton design pattern</typeparam>
public abstract class Singleton<T> where T:class
{
#region STATIC DATA MEMBERS
/// <summary>
/// The single instance of the subclass
/// </summary>
private static T singletonInstance;

/// <summary>
/// Object instance is used for concurrency control
/// </summary>
private static readonly object lockingObject = new object();
#endregion


#region STATIC METHODS
/// <summary>
/// Returns the instance of the class that derives from this class or creates an
/// instance if one does not already exist.
/// </summary>
/// <returns>The instance of the class derived from Singleton</returns>
public static T GetInstance()
{
lock (lockingObject)
{
if (SingletonInstance == null)
{
// Use reflection to instantiate a new instance of the class T. This
// is required as instantiating a new instance directly (new T) would
// violate the basic principle of why the sinleton pattern is used as there
// would have to be a public constructor
SingletonInstance = UtilityHelper.ConstructParameterlessInstanceOfType<T>(BindingFlags.Instance | BindingFlags.NonPublic);
}
}

return SingletonInstance;
}


/// <summary>
/// Gets the single instance of the sub-class that derives from this Singleton
/// </summary>
protected static T SingletonInstance
{
get
{
return singletonInstance;
}
set
{
singletonInstance = value;
}
}

/// <summary>
/// Re-initializes the singleton instance by causes the instance to be instantiated
/// as a new instance. This can be used, for example, when changes to configuration
/// have been made.
/// </summary>
/// <returns>A new instance of the type that sub-classes from this type</returns>
public static T Reinitialize()
{
lock (lockingObject)
{
SingletonInstance = null;
}

return GetInstance();
}
#endregion
}

An can be seen from the code, if an instance of the type that does exist than a
new instance is created by invoking the private constructor of that type.
The code for this method is shown below:


/// <summary>
/// Constructs a dynamic instance of the type T by invoking the
/// private or protected parameterless contructor of that type. This
/// primarily can be used to instantiate singleton instances (as by
/// definition they must not have a public constructor).
/// </summary>
/// <typeparam name="T">The type to instantiate</typeparam>
/// <returns>An instance of the type T</returns>
public static T ConstructParameterlessInstanceOfType<T>(BindingFlags bindingFlags) where T:class
{
ConstructorInfo constructor = typeof(T).GetConstructor(
bindingFlags,
null,
new Type[0],
new ParameterModifier[0]);

T instance = null;

if (constructor == null)
{
// Type does not have a private or protected parameterless constructor
throw new MemberAccessException(String.Format(CultureInfo.CurrentCulture, "Type {0} does not have the expected constructor (public or private parameterless constructor)", typeof(T).Name));
}
else
{
// Instantiate a new instance of the type by invoking the private or protected constructor
instance = constructor.Invoke(new object[0]) as T;

if (instance == null)
{
throw new MemberAccessException(String.Format(CultureInfo.CurrentCulture, "Unable to create an instance of the type {0}", typeof(T).Name));
}
}

return instance;
}

Singleton derived classes must have a private or protected parameterless constructor.
There is no check for a public constructor but this could easily be added.

Example

The following class demostrates how the is-a relationship can be established
with Singleton.



/// <summary>
/// MicrosoftExceptionHandlingManager provides an exception handling
/// class that is coupled (uses) the Microsoft Patterns & Practices
/// library.
/// </summary>
public class MicrosoftExceptionHandlingManager : Singleton<MicrosoftExceptionHandlingManager>, IExceptionHandlingManager
{
#region CONSTRUCTORS
/// <summary>
/// Private constructor that is required in order for this to be
/// treated as a singleton
/// </summary>
private MicrosoftExceptionHandlingManager()
{
}
#endregion

#region METHODS
/// <summary>
/// Handles an exception by logging it to logging sinks as configured
/// using the Microsoft Enterprise Library V4.0. The specific way an exception
/// is handled can be specified by using the configuration tool that comes
/// supplied with the library.
/// </summary>
/// <param name="ex">The exception to handle</param>
/// <param name="exceptionHandlingPolicy">The policy to use for handling the exception (which relates to the policies in the configuration)</param>
public void LogException(Exception ex, string exceptionHandlingPolicy)
{
bool reThrow = ExceptionPolicy.HandleException(ex, exceptionHandlingPolicy);

if (reThrow == true)
{
throw ex;
}
}
#endregion
}

The two important points about the sample are:

  1. The class is-a Singleton by deriving from Singleton and passing the class name as the type parameter.
  2. The class must have a private or protected constructor.
An example of the code to get a reference to the instance:


MicrosoftExceptionHandlingManager.GetInstance()

Testing Extension Points

  • Performance testing as locking is used
Evolution Extension Points
  • The GetInstance static methods checks that the type T does NOT have a public constructor