UPDATE: I chagned the design today so only one instance of T gets created irrespective of IFactory<T> usage by inserting another base class.
void Main()
{
var a = Singleton<MyClass>.Value;
var b = Singleton<MyClass, MyClassFactory>.Value;
var c = Singleton<MyClass>.Value;
var d = Singleton<MyClass, MyClassFactory>.Value;
var e = Singleton<MyOtherClass>.Value;
var f = Singleton<MyOtherClass>.Value;
var g = Singleton<MyOtherClass, MyOtherFactory>.Value;
var h = Singleton<MyOtherClass, MyOtherFactory>.Value;
}
class SingletonBase
{
protected static object Locker = new LockerObject();
}
class SingletonValue<T>Singleton<T> : SingletonBase
{
where protectedT static: Tnew() StaticT;
}
{
class Singleton<T> : SingletonValue<T> wherestatic T : new() StaticT;
{
public static T Value
{
get
{
lock (Locker)
{
if(StaticT == null)
{
StaticT = Activator.CreateInstance<Factory<T>>().Create();
}
else
{
Console.WriteLine ("Singleton<T>::Value" + typeof(T).Name + " is already created");
}
}
return StaticT;
}
}
}
class Singleton<T, F> : SingletonValue<T>SingletonBase where T : new() where F : IFactory<T>, new()
{
static T StaticT;
public static T Value
{
get
{
lock (Locker)
{
if(StaticT == null)
{
StaticT = new F().Create();
}
else
{
Console.WriteLine ("Singleton<T, F>::Value" + typeof(T).Name + " is already created");
}
}
return StaticT;
}
}
}
class LockerObject
{
Guid myGUID;
public LockerObject()
{
this.myGUID = Guid.NewGuid();
Console.WriteLine ("New LockerObject " + this.myGUID.ToString());
}
}
interface IFactory<T>
{
T Create();
}
class Factory<T> : IFactory<T> where T : new()
{
public T Create()
{
Console.WriteLine ("Factory<T>::Create()");
return new T();
}
}
class MyClassFactory : IFactory<MyClass>
{
public MyClass Create()
{
Console.WriteLine ("MyClassFactory::Create()");
return new MyClass();
}
}
class MyClass
{
public MyClass()
{
Console.WriteLine ("MyClass created");
}
}
class MyOtherClass
{
public MyOtherClass()
{
Console.WriteLine ("MyOtherClass created");
}
}
class MyOtherFactory : IFactory<MyOtherClass>
{
public MyOtherClass Create()
{
Console.WriteLine ("MyOtherFactory::Create()");
return new MyOtherClass();
}
}
Output::
New LockerObject aa1a940336aa2282-621fd745-43f943ca-bbaf84d2-449c84826cba998a78e39d51
Factory<T>::Create()
MyClass created
Singleton<T, F>::ValueMyClass is already created
Singleton<T>::ValueMyClass is already created
Singleton<T, F>::ValueMyClass is already created
Factory<T>MyClassFactory::Create()
MyOtherClassMyClass created
Singleton<T>::ValueMyOtherClass is already created
Singleton<T, F>::ValueMyOtherClassValueMyClass is already created
Singleton<T, F>::ValueMyOtherClassValueMyClass is already created