Click here to Skip to main content
Click here to Skip to main content

Generic Singleton Provider

By , 26 Jul 2005
 

Introduction

Many people from different programming backgrounds should be familiar with the Singleton Pattern. Those who use it will find that they often have to write the same code each time they want to create a different Singleton class. With the advent of C# 2.0 Generics, it is possible to write this code only once.

Background

There are many articles about the Singleton Pattern. Probably the most comprehensive one for C# can be found here: "Implementing the Singleton Pattern in C#".

There is an increasing amount written about C# Generics. For example, a CodeProject article can be found here: "Generics in C# 2.0" by Ansil.

Using C# 2.0 Generics to achieve a reusable Singleton pattern

Using C# 2.0 Generics, it is possible to create what I have called a 'Singleton Provider'. This is a class that can be used repeatedly to instantiate a class as a singleton without having to re-write the singleton pattern code for that specific class. This has the added benefit of separating singleton code from the class code leaving the flexibility to use several instances of the class or using the class as a singleton.

The singleton code used in this example is based on the fifth example described in the above article about implementing the Singleton Pattern in C#:

    public sealed class Singleton
    {
        Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                return SingletonCreator.instance;
            }
        }
        
        class SingletonCreator
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }

            internal static readonly Singleton instance = new Singleton();
        }
    }

With an understanding of Generics, you can see that there should be no reason to replace the type arguments in this block of code with the typical 'T' found in Generics. If this is done, the code looks like this.

    public class SingletonProvider <T> where T:new()
    {
        SingletonProvider() {}

        public static T Instance
        {
            get { return SingletonCreator.instance; }
        }

        class SingletonCreator
        {
            static SingletonCreator() { }

            internal static readonly T instance = new T();
        }
    }

Note that the Generics must have a constraint on it. This constraint forces any type 'T' to have a default constructor, that is, a constructor that takes no parameters. This allows the SingletonCreator to instantiate the type 'T'.

So, how does one use the SingletonProvider? To understand how to use this, we need a test class. The test class has two features. The first is a default constructor that sets a timestamp member variable. The second is a public method that writes that timestamp using Debug.WriteLine. This setup means that no matter which thread uses this class in the Singleton Pattern, whenever that public method is called, it should output the same value.

    public class TestClass
    {
        private string _createdTimestamp;

        public TestClass ()
        {
            _createdTimestamp = DateTime.Now.ToString();
        }

        public void Write()
        {
            Debug.WriteLine(_createdTimestamp);
        }
    }

The class is used with the SingletonProvider as follows:

    SingletonProvider<TestClass>.Instance.Write();

Points of Interest

I have tested this code with a Dual Processor with hyper-threading enabled with 100 threads accessing the singleton. They all output the same value illustrating that this is a thread-safe generic way to create singletons.

I believe that this is a really neat illustration of how Generics can save you writing code.

History

This is the first iteration of this code, please provide any feedback as to whether you have used this or not or any problems that anyone has found with it!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

davojc
Web Developer
United Kingdom United Kingdom
Member
I have been developing primarily with .NET for over 10 years now although I have previous experience with Java and C++.
 
Programming is very much only a work task. I rarely do anything programming related in my spare time.
 
And no, this isn't a recent picture Smile | :)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralUsing this on Formsmembernothinking2 Mar '07 - 5:24 
Btw this is a great implementation and it works great. However I have found that when trying to apply it to forms it has a problems. When I close a form the object gets disposed but when I want to open the form again it refers to the disposed object instead of creating a new one. Is there something else that could be add that will make it do that? I know i could just hide the forms instead of closing them but that sounds messy.
GeneralRe: Using this on FormsmemberAntonio David Gonzlez10 May '07 - 7:43 
I have the same problem. This is a draft of my solution.
Sorry, it's te bad code first pattern and in vb.net, but you can get the idea
 
Public Class FormSingletonProvider(Of itemtype As {New, System.Windows.Forms.Form})
 
Public Sub New()
End Sub
 
Private Shared _instance As itemtype = Nothing
 
Public Shared ReadOnly Property Instance() As itemtype
Get
If _instance Is Nothing OrElse _instance.IsDisposed Then
_instance = New itemtype
End If
Return _instance
End Get
End Property
 
End Class
AnswerRe: Using this on FormsmemberLusid Insanity14 May '07 - 9:41 
Here's a special implementation of this that I came up with that handles anything deriving from Control differently than anything else. It's a little bit better than the other guy's implementation, IMHO, because it uses reflection to allow a single class to handle both disposable control types as well as anything else. You just have to be your own judge of whether the performance hit of a tiny bit of reflection scares you or not.
 
public class Singleton where T : new()
{
static private T _instance;
static public T Instance
{
get
{
if (_instance is Control)
{
Type t = typeof(T);
if ((bool)t.GetProperty("IsDisposed").GetValue(_instance, null))
_instance = default(T);
}
 
if (_instance == null)
_instance = new T();
return _instance;
}
}
}

GeneralRe: Using this on Formsmemberggeurts14 May '07 - 22:57 
If you have a need to dispose an object and recreate it again, you shouldn't use the singleton design pattern in the first place. It is not meant for use in the scenario that you describe!
 
If you need to hold onto a reference to an object that should automatically become null/Nothing when the object goes away, you should have a look at the WeakReference class.
 
Regards,
Gerke.
 

GeneralRe: Using this on Formsmembernothinking21 May '07 - 16:36 
Thanks Lusid Insanity I'll give it a try.
 
Gerke does that solution keep only one instance of my form open? The thing is I want to only allow one open at a time.
AnswerRe: Using this on Formsmemberggeurts22 May '07 - 5:47 
If you use the singleton pattern with the reference to your form stored in a WeakReference field, you ensure you have no more than one form active, but the form is not kept alive by the singleton.
 
Here is a code sample to get you started, though I still would have strong doubts about any design that requires this monster...
 
namespace WeakSingletonDemo
{
      using System;
      using System.Diagnostics;
      using System.Threading;
 
      public class WeakSingleton&lt;T&gt;
            where T: class, new()
      {
            private static WeakReference _instance = new WeakReference(null);
            private static object _instanceLock = new object();
 
            public static T Instance
            {
                  get
                  {
                        T result = (T) _instance.Target;
                        if (result == null)
                        {
                              lock (_instanceLock)
                              {
                                    result = (T) _instance.Target;
                                    if (result == null)
                                    {
                                          result = new T();
                                          _instance.Target = result;
                                    }
                              }
                        }
                        return result;
                  }
            }
      }
 
      class Program
      {
            private class Message
            {
                  private static int _nextMessageId = 1;
                  public readonly string Text = string.Format("Message #{0}.", _nextMessageId++);
            }
 
            static void Main(string[] args)
            {
                  Message firstMessage = WeakSingleton&lt;Message&gt;.Instance;
                  string firstMessageText = firstMessage.Text;
                 
                  GC.Collect();
                  Debug.Assert(WeakSingleton&lt;Message&gt;.Instance.Text == firstMessageText,
                        "Message singleton has not released during garbage collection, because strong references still exist.");
 
                  firstMessage = null;
                  GC.Collect();
                  Debug.Assert(WeakSingleton&lt;Message&gt;.Instance.Text != firstMessageText,
                        "Message singleton has been released during garbage collection, because there were no strong references left.");
            }
      }
}
 
Regards,
<a href = "http://www.geurtsrus.com/gerke" rel="nofollow">Gerke</a>.
Questionusing SingletonProvider to create types on the flymemberJonathan Karlen5 Feb '07 - 5:43 
If I have a series of objects that are all derived from the same base call how would I go about using SingletonProvider to create instances of the derived classes on the fly at run time. I'd envision a method similar to:
 
private void x(string GenericClassName)
{
GenericClass y = SingletonProvider.Instance;
y.DoSomething();
}
 
But I can't find a way to make this happen. Any advice would be appreciated.
 
Thanks,
JK

AnswerRe: using SingletonProvider to create types on the flymembermercede18 Jul '08 - 21:12 
Creating types on the fly simply means extremely bad design. I cant think of any situation that requires you creating types on the fly. If still you are in need of such then you can try this:
declare the Singleton classes for every class you may require and use a switch statement to decide which one to instantiate
GeneralPointer to article where private on test class will prevent instantiation and force SingletonmemberWray Smallwood29 Nov '06 - 4:36 
http://www.codeproject.com/cs/design/GenericSingletonPattern.asp
QuestionThis way prevents a class being instantiated at allmembercrellbar20 Apr '06 - 5:13 
Ive only used c# sharp a little and found this article v. helpful for my project as I hadnt encountered generics before it.
 
Here is the code I generated, does anyone know of a better way than using the lock?
 
This method prevents you from using the new keyword on a class that must always be a singleton.
 

using System;
using System.Collections.Generic;
using System.Text;
 
namespace AIBG
{
public class Singleton where T : new()
{
private static T instance = new T();
private static readonly object padlock = new object();
 
public static T Instance
{
get
{
lock (padlock)
{
if (instance == null) instance = new T();
}
return instance;
}
}
 
protected Singleton()
{
if (instance != null)
{
throw (new Exception("You have tried to create a new singleton class where you should have instanced it. Replace your \"new class()\" with \"class.Instance\""));
}
}
}
 

public class MySingletonClass:Singleton {
public void scream() {
Console.WriteLine("Argh.");
}
 
public MySingletonClass() {
Console.WriteLine("Making instance of My Singleton Class.");
}
}
 
class Demo {
public static void main() {
//MySingletonClass o0 = new MySingletonClass(); // Throws simple exception
MySingletonClass o1 = MySingletonClass.Instance;
MySingletonClass o2 = MySingletonClass.Instance;
//MySingletonClass o3 = new MySingletonClass(); // Throws simple exception
o1.scream();
o2.scream();
Console.ReadLine();
}
}
}
 

 
Any suggestions would be great. Big Grin | :-D
 
CBAR

 
-- modified at 9:22 Friday 21st April, 2006

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 26 Jul 2005
Article Copyright 2005 by davojc
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid