/
SingletonBase.cs
140 lines (116 loc) · 4.75 KB
/
SingletonBase.cs
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**************************************************************************
* File Name:SingletonBase.cs
* Description:SingletonBase.cs class description...
* Copyright:Copyright © 2020 LeoYang-Chuese. All rights reserved.
* Creator:Leo Yang
* Create Time:2020/12/15
*Project Address:https://github.com/LeoYang-Chuese/wif
**************************************************************************/
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
namespace Frontier.Wif.Core.Generic
{
/// <summary>
/// To recap, in order to create a singleton class using the singleton base class, you need to do the following:
///
/// 1) Define a sealed class which derives from SingletonBase[T], where T is the class name you are defining. It ensures that you cannot create subclasses from this singleton class.
/// 2) Define a single parameterless private constructor inside the class. It ensures that no instances of this class can be created externally.
/// 3) Access the class’ singleton instance and public members by calling the Instance property.
///
/// got this implementation from https://github.com/denni/liquidsilver
/// http://csharpindepth.com/Articles/General/Singleton.aspx#introduction
///
/// also show http://www.yoda.arachsys.com/csharp/singleton.html
///
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class SingletonBase<T> where T : class
{
#region Properties
/// <summary>
/// Gets the singleton instance of this class.
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
public static T Instance => SingletonFactory.Instance;
#endregion
#region Constructors
#endregion
/// <summary>
/// The singleton class factory to create the singleton instance.
/// </summary>
private class SingletonFactory
{
#region Fields
/// <summary>
/// Defines the singleton instance.
/// </summary>
private static WeakReference _instance;
#endregion
#region Properties
/// <summary>
/// Gets the singleton of the given type.
/// </summary>
internal static T Instance
{
get
{
if (!(_instance?.Target is T comparer))
{
comparer = GetInstance();
_instance = new WeakReference(comparer);
}
return comparer;
}
}
#endregion
#region Constructors
// Prevent the compiler from generating a default constructor.
/// <summary>
/// Prevents a default instance of the <see cref="SingletonFactory"/> class from being created.
/// </summary>
private SingletonFactory()
{
}
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
/// <summary>
/// Initializes static members of the <see cref="SingletonFactory"/> class.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
static SingletonFactory()
{
}
#endregion
#region Methods
/// <summary>
/// The GetInstance
/// </summary>
/// <returns>The <see cref="T"/></returns>
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId =
"System.Type.InvokeMember")]
private static T GetInstance()
{
var theType = typeof(T);
T inst;
try
{
inst = (T) theType.InvokeMember(theType.Name,
BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic,
null, null, null,
CultureInfo.InvariantCulture);
}
catch (MissingMethodException ex)
{
throw new TypeLoadException(
string.Format(CultureInfo.CurrentCulture,
"The type '{0}' must have a private constructor to be used in the Singleton pattern.",
theType.FullName), ex);
}
return inst;
}
#endregion
}
}
}