C # Singleton pattern with triggered initialization

I need a singleton that:

  • - lazy bootloader
  • is thread safe
  • loads some values ​​when building
  • these values ​​can be requested at any time
  • Initialization MAY occur at some exact time before the request begins, so I must somehow call it from the outside. Of course, starting several times should only initialize once.

I am using .NET 3.5.

I started with a Jon Skeet implementation (version 5) using a static subclass:

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(); } } 

This ticks almost all fields except "trigger initialization from the outside." Since the actual initialization takes place inside ctor, this can happen more than once.

How can I do that?

Singleton will be used as follows:

 public static void Main(){ //do stuff, singleton should not yet be initialized. //the time comes to initialize the singleton, eg 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; } 
+7
source share
6 answers

It looks like you could:

 public sealed class Singleton { IEnumerable<string> Values {get; private set;} private Singleton(bool loadDefaults) { if (loadDefaults) Values = new[]{"quick", "brown", "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); } } } } } 

Or create one instance to be updated:

 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 static object instanceLock = new object(); private static bool isInitialized = false; public static void Initialize() { lock(instanceLock) { if (!isInitialized) { isInitialized = true; Instance.Values = new[]{"another", "set", "of", "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(); } } 

And the third option, based on your constant comment and deleting the comment of the nested class:

 public sealed class Singleton { IEnumerable<string> Values {get; private set;} private Singleton() { Values = new[]{"quick", "brown", "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(); } } } } 
+3
source

You can configure the Initialize method, which can be started from the outside, if you need to initialize later, but if the values ​​are different each time you start, then this cannot be static, which violates the Singleton pattern.

According to your example, which has no variables, I assume that you just delay when initialization occurs (procedure, not constructor), but your question suggests that you want different values, but if multiple initializations happen close to each other , it only initializes once, so I'm a little confused by this.

I’m not sure that you only need Singleton implantation, but I can’t completely answer without information about whether the Initializer () runs the same code each time or has some type of variable.

0
source

You can use a double control pattern. Just add the following code to the Singleton field:

 public sealed class Singleton { .......................... private static object locker = new object(); private static bool initialized = false; public static void Initialize() { if (!initialized){ lock(locker) { if (!initialized){ //write initialization logic here initialized = true; } } } } ....................... } 
0
source

You can do something like this

 public sealed class Singleton { IEnumerable<string> Values { get; set; } private Singleton() { Console.WriteLine("-- Private Singleton constructor"); Values = new[] { "quick", "brown", "fox" }; } public static Singleton Instance { get { Console.WriteLine("- Singleton Instance"); return Nested.instance; } } public static void Initialize() { Console.WriteLine("- Singleton Initialize"); Nested.Initialize(); } internal class Nested { private static object syncRoot = new object(); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() { Console.WriteLine("-- Static Nested constructor"); } internal static readonly Singleton instance = new Singleton(); internal static void Initialize() { lock (syncRoot) { Console.WriteLine("-- Locked"); Console.WriteLine("--- Nested Initialize"); Console.WriteLine("-- Unlocked"); } } } } 

Using

 class Program { static void Main(string[] args) { var i = Singleton.Instance; i = Singleton.Instance; Console.WriteLine("-----"); Singleton.Initialize(); Singleton.Initialize(); Singleton.Initialize(); Console.Read(); } } 

What are the exits

 - Singleton Instance -- Private Singleton constructor -- Static Nested constructor - Singleton Instance ----- - Singleton Initialize -- Locked --- Nested Initialize -- Unlocked - Singleton Initialize -- Locked --- Nested Initialize -- Unlocked - Singleton Initialize -- Locked --- Nested Initialize -- Unlocked 
0
source
 public class Singleton<T> where T : class, new() { private static T instance; public static T Instance { get { if (instance == null) { throw new Exception("singleton needs to be initialised before use"); } return instance; } } public static void Initialise(Action<T> initialisationAction) { lock(typeof(Singleton<T>)) { if (instance != null) { return; } instance = new T(); initialisationAction(instance); } } } 
0
source

The first idea I chose was to just use the throwaway variable assigned to the singleton instance, which (maybe?) Starts initialization

 static Main() { var unused = Singleton.Instance; //this should initialize the singleton, unless the compiler optimizes it out. //I wonder if the compiler is smart enough to see this call has side effects. var vals = Singleton.Instance.Values; } 

... but side-effect programming is something I try to avoid, so let's make the intention clearer.

 public class Singleton { public static void Initialize() { //this accesses the static field of the inner class which triggers the private Singleton() ctor. Instance._Initialize(); } private void _Initialize() { //do nothing } [the rest as before] } 

therefore use will be:

 static Main() { //still wondering if the compiler might optimize this call out Singleton.Initialize(); var vals = Singleton.Instance.Values; } 

Btw this will also work:

 static Main() { var vals = Singleton.Instance.Values; } 

Compiler optimization, I think this applies to all requirements.

0
source

All Articles