1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
/// <summary>
/// This class provide a generic and thread-safe interface for Singleton classes.
/// </summary>
/// <typeparam name="T">The specialized singleton which is derived
/// from SingletonBase<T></typeparam>
public abstract class SingletonBase<T>
where T : SingletonBase<T>
{
/* the lock object */
private static object _lock = new object();
/* the static instance */
private static T _instance = null;
/// <summary>
/// Get the unique instance of <typeparamref name="T"/>.
/// This property is thread-safe!
/// </summary>
public static T Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
/* Create a object without to use new (where you need a public ctor) */
object obj = FormatterServices.GetUninitializedObject(typeof(T));
if (obj != null) // just 4 safety, but i think obj == null shouldn't be possible
{
/* an extra test of the correct type is redundant,
* because we have an uninitialised object of type == typeof(T) */
_instance = obj as T;
_instance.Init(); // now the singleton will be initialized
}
}
}
}
else
{
_instance.Refresh(); // has only effect if overridden in sub class
}
return _instance;
}
}
/// <summary>
/// Called while instantiation of singleton sub-class.
/// This could be used to set some default stuff in the singleton.
/// </summary>
protected virtual void Init()
{ }
/// <summary>
/// If overridden this will called on every request of the Instance but
/// the instance was already created. Refresh will not called during
/// the first instantiation, for this will call Init.
/// </summary>
protected virtual void Refresh()
{ }
}
// usage:
class SingletonTest
: SingletonBase<SingletonTest>
{
~SingletonTest()
{ Console.WriteLine("~SingletonTest called ..."); }
public void DoSomething()
{ Console.WriteLine("SingletonTest::DoSomething called ..."); }
public void DoAnother()
{ Console.WriteLine("SingletonTest::DoAnother called ..."); }
protected override void Init()
{ Console.WriteLine("SingletonTest::Init called ..."); }
protected override void Refresh()
{ Console.WriteLine("SingletonTest::Refresh called ..."); }
}
public class Program
{
public static void Main(string[] args)
{
SingletonTest.Instance.DoSomething();
SingletonTest.Instance.DoAnother();
Console.WriteLine("press any key ...");
Console.ReadKey(true);
}
}
|