我需要一个单身人士:
>是懒惰加载
>是线程安全的
>在施工时加载一些值
>可以随时查询这些值
>初始化可能在查询开始之前的某个精确时间发生 – 所以我必须能够以某种方式从外部触发它.当然,多次触发应该只进行一次初始化.
我使用.NET 3.5.
我使用静态子类开始使用Jon Skeet的implementation(第5版):
public sealed class Singleton { IEnumerable<string> Values {get; private set;} private Singleton() { Values = new[]{"quick","brown","fox"}; } public static Singleton Instance { get { return Nested.instance; } } private class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() { } internal static readonly Singleton instance = new Singleton(); } }
除了“从外部触发初始化”之外,几乎所有方框都会打勾.由于实际初始化发生在ctor内部,因此不会发生多次.
如何实现这一目标?
单例将使用如下:
public static void Main(){ //do stuff,singleton should not yet be initialized. //the time comes to initialize the singleton,e.g. a database connection is available //this may be called 0 or more times,possibly on different threads Singleton.Initialize(); Singleton.Initialize(); Singleton.Initialize(); //actual call to get retrieved values,should work var retrieveVals = Singleton.Instance.Values; }
解决方法
好像你可以这样做:
public sealed class Singleton { IEnumerable<string> Values {get; private set;} private Singleton(bool loadDefaults) { if (loadDefaults) Values = new[]{"quick","fox"}; else Values = new[]{"another","set","of","values"}; } public static Singleton Instance { get { return Nested.instance; } } public static void Initialize() { Nested.Initialize(); } private class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() { } internal static readonly Singleton instance = new Singleton(true); private static object instanceLock = new object(); private static bool isInitialized = false; public static void Initialize() { lock(instanceLock) { if (!isInitialized) { isInitialized = true; instance = new Singleton(false); } } } } }
或者创建一个将要更新的单个实例:
public sealed class Singleton { IEnumerable<string> Values {get; private set;} private Singleton() { Values = new[]{"quick","fox"}; } public static Singleton Instance { get { return Nested.instance; } } private static object instanceLock = new object(); private static bool isInitialized = false; public static void Initialize() { lock(instanceLock) { if (!isInitialized) { isInitialized = true; Instance.Values = new[]{"another","values"}; } } } private class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() { } internal static readonly Singleton instance = new Singleton(); } }
第三个变体基于您的不可变注释和删除嵌套类注释:
public sealed class Singleton { IEnumerable<string> Values {get; private set;} private Singleton() { Values = new[]{"quick","fox"}; } private static Singleton instance; private static object instanceLock = new object(); public static Singleton Instance { get { Initialize(); return instance; } } public static void Initialize() { if (instance == null) { lock(instanceLock) { if (instance == null) instance = new Singleton(); } } } }