Generic Singleton<T>
The problem with a generic singleton factory is that since it is generic you do not control the "singleton" type that is instantiated so you can never guarantee that the instance you create will be the only instance in the application.
If a user can provide a type to as a generic type argument then they can also create instances of that type. In other words, you cannot create a generic singleton factory - it undermines the pattern itself.
this is my point using .NET 4
public class Singleton<T> where T : class, new()
{
private Singleton (){}
private static readonly Lazy<T> instance = new Lazy<T>(()=> new T());
public static T Instance { get { return instance.Value; } }
}
Usage pattern:
var journalSingleton = Singleton<JournalClass>.Instance;
Here is my implementation using a non-public constructor. The only issue right now is there is no way to have a custom constraint on C# generics, so I have to throw a run-time exception for derived classes with public default constructors instead of a compile-time error.
using System;
using System.Reflection;
using System.Threading;
/// <summary>
/// A generic abstract implementation of the Singleton design pattern (http://en.wikipedia.org/wiki/Singleton_pattern).
///
/// Derived type must contain a non-public default constructor to satisfy the rules of the Singleton Pattern.
/// If no matching constructor is found, an exception will be thrown at run-time. I am working on a StyleCop
/// constraint that will throw a compile-time error in the future.
///
/// Example Usage (C#):
///
/// class MySingleton : Singleton<MySingleton>
/// {
/// private const string HelloWorldMessage = "Hello World - from MySingleton";
///
/// public string HelloWorld { get; private set; }
///
/// // Note: *** Private Constructor ***
/// private MySingleton()
/// {
/// // Set default message here.
/// HelloWorld = HelloWorldMessage;
/// }
/// }
///
/// class Program
/// {
/// static void Main()
/// {
/// var mySingleton = MySingleton.Instance;
/// Console.WriteLine(mySingleton.HelloWorld);
/// Console.ReadKey();
/// }
/// }
/// </summary>
/// <typeparam name="T">Type of derived Singleton object (i.e. class MySingletone: Singleton<MySingleton>).</typeparam>
public abstract class Singleton<T> where T : class
{
/// <summary>
/// "_instance" is the meat of the Singleton<T> base-class, as it both holds the instance
/// pointer and the reflection based factory class used by Lazy<T> for instantiation.
///
/// Lazy<T>.ctor(Func<T> valueFactory,LazyThreadSafetyMode mode), valueFactory:
///
/// Due to the fact Lazy<T> cannot access a singleton's (non-public) default constructor and
/// there is no "non-public default constructor required" constraint available for C#
/// generic types, Lazy<T>'s valueFactory Lambda uses reflection to create the instance.
///
/// Lazy<T>.ctor(Func<T> valueFactory,LazyThreadSafetyMode mode), mode:
///
/// Explanation of selected mode (ExecutionAndPublication) is from MSDN.
///
/// Locks are used to ensure that only a single thread can initialize a Lazy<T> instance
/// in a thread-safe manner. If the initialization method (or the default constructor, if
/// there is no initialization method) uses locks internally, deadlocks can occur. If you
/// use a Lazy<T> constructor that specifies an initialization method (valueFactory parameter),
/// and if that initialization method throws an exception (or fails to handle an exception) the
/// first time you call the Lazy<T>.Value property, then the exception is cached and thrown
/// again on subsequent calls to the Lazy<T>.Value property. If you use a Lazy<T>
/// constructor that does not specify an initialization method, exceptions that are thrown by
/// the default constructor for T are not cached. In that case, a subsequent call to the
/// Lazy<T>.Value property might successfully initialize the Lazy<T> instance. If the
/// initialization method recursively accesses the Value property of the Lazy<T> instance,
/// an InvalidOperationException is thrown.
///
/// </summary>
private static readonly Lazy<T> _instance = new Lazy<T>(() =>
{
// Get non-public constructors for T.
var ctors = typeof (T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
// If we can't find the right type of construcor, throw an exception.
if (!Array.Exists(ctors, (ci) => ci.GetParameters().Length == 0))
{
throw new ConstructorNotFoundException("Non-public ctor() note found.");
}
// Get reference to default non-public constructor.
var ctor = Array.Find(ctors, (ci) => ci.GetParameters().Length == 0);
// Invoke constructor and return resulting object.
return ctor.Invoke(new object[] {}) as T;
}, LazyThreadSafetyMode.ExecutionAndPublication);
/// <summary>
/// Singleton instance access property.
/// </summary>
public static T Instance
{
get { return _instance.Value; }
}
}
/// <summary>
/// Exception thrown by Singleton<T> when derived type does not contain a non-public default constructor.
/// </summary>
public class ConstructorNotFoundException : Exception
{
private const string ConstructorNotFoundMessage = "Singleton<T> derived types require a non-public default constructor.";
public ConstructorNotFoundException() : base(ConstructorNotFoundMessage) { }
public ConstructorNotFoundException(string auxMessage) : base(String.Format("{0} - {1}", ConstructorNotFoundMessage, auxMessage)) { }
public ConstructorNotFoundException(string auxMessage, Exception inner) : base(String.Format("{0} - {1}", ConstructorNotFoundMessage, auxMessage), inner) { }
}