Tuesday, October 4, 2011

ControlledSingleton pattern

Some months back I had written a post to describe how to get the name of the calling method programmatically. ie to get the call stack entry just below the current method. That post was born in relation with one of our requirement to create controlled singleton pattern which I described in it’s previous post.

Why we need ControlledSingleton pattern?

This is needed when you plan to make a class Singleton after so much code is written using that class and you have technical and managerial limitations to change all the existing code.The normal singleton pattern with private constructor will not be applicable here since it needs full inspection in your code base for compilation as well as usage of reflection. You can easily fix the compilation issues but reflection cannot be caught that much easily.Also if you are serializing the Singleton class to persist its state or pass through WCF, certainly you cannot make it as singleton otherwise the serializer will fail.

If your company management in case of product development or you client in case of projects are really adamant on quality and are ready to give you enough time to refactor code,just go with that and implement the real singleton. Also if you are developing a new project you can decide on which class to be singleton and make that as normal singleton class.Unfortunately I didn’t had this luxury which lead me to the ControlledSingleton pattern.

What is ControlledSingleton

According to me it’s same as normal singleton but giving permission to some components to create the object of singleton class.The components may be some classes,some methods or some assemblies.That depends on the requirements of the developer who implements the pattern. I am not sure whether there are any other pattern in different name which is same as this.

Implementing ControlledSingleton

This depends upon the environment / programming language you are using.Since I am a .net developer I can see 2 methods to implement the pattern

  1. Validating the caller using call stack
    This can be achieved by inspecting the current call stack and checking whether the caller has the permission to create the object.Please refer my previous posts to get detailed idea.
    http://joymonscode.blogspot.com/2011/02/how-to-get-calling-method-name.html

    Characteristics:-The draw back of this method is we cannot ensure singleton at compile time.Each and every time before inspecting the call stack will cause performance impacts. This is applicable only in managed languages where we have the method name at runtime.
  2. InternalsVisibleTo attribute
    The InternalsVisibleToAttribute defined on assembly tells the system that there are some more assemblies which can see it’s internal members. That means if we make a class Singleton using internal constructor the assemblies which are specified in the InternalsVisibleTo attribute can create the object of the singleton class.

    Characteristics:-The advantage of this is we can ensure at the compile time itself. This idea can also extend to unmanaged languages too since it works at compile time.

About attached sample

The sample contains 3 projects. “ControlledSingleton” project contains the singleton class PersonsContext. The class is made as Singleton using internal constructor which means any class inside that project can create the instance of the singleton class. The InternalsVisibleTo attribute is pointing to the second assembly named “SingletonPermitted”.ie it can create object of PersonContext.The “ControlledSingleton_Demo” is a console application which don’t have permission to create the object of singleton class. It cannot even try to use reflection to create the object.

Download the sample from here.

Recommended changes

The above methods allows so many objects of the singleton class in the system at same time.If you don’t have serialization on your singleton candidate you can think about a ReInitializeSingleton method which is internal to modify/replace the single ton object.

internal ReinitializeSingleton(params)

No comments: