Skip to main content

Pattern for re-throwing exceptions caused during Singleton initialization. If you are doing provider or other similar constructs that have late-constructed singleton behavior, you need to be sure that anyone using the singleton will not proceed with an erroneously constructed object. But how do you let them know something went wrong originally? Simply rethrow the original exception again! This pattern is from the "System.Web.Profile.ProviderBase" class thanks to Reflector.

public class Default : Singleton
{
    public Default()
    {
        // anything else you really want to happen in the instance constructor...
    }
}

public class Singleton
{
    private static bool s_Initialized;
    private static object s_InitializeLock;
    private static Exception s_InitializeException;
    private static Singleton s_Instance;

    static Singleton()
    {
        s_InitializeLock = new object();
        s_InitializeException = null;
        s_Initialized = false;
        s_Instance = null;
    }

    protected Singleton()
    {
        if (!s_Initialized)
        {
            InitializeStatic();
        }

        // anything else you really want to happen in the
        // base constructor...
    }

    public void Create()
    {
        InitializeStatic();

        if (s_Instance != null)
        {
            return s_Instance;
        }

        lock (s_InitializeLock)
        {
            if (s_Instance == null)
            {
                s_Instance = new Default();
            }

            return s_Instance;
        }
    }

    private static void InitializeStatic()
    {
        if (s_Initialized)
        {
            if (s_InitializeException != null)
            {
                throw s_InitializeException;
            }
        }
        else
        {
            lock (s_InitializeLock)
            {
                if (s_Initialized)
                {
                    if (s_InitializeException != null)
                    {
                        throw s_InitializeException;
                    }

                    return;
                }
                try
                {
                    // do real singleton initialization
                }
                catch (Exception ex)
                {
                    if (s_InitializeException == null)
                    {
                        s_InitializeException = ex;
                    }
                }

                s_Initialized = true;
            }

            if (s_InitializeException != null)
            {
                throw s_InitializeException;
            }
        }
    }

    internal static Singleton Instance
    {
        get
        {
            InitializeStatic();
            return s_Instance;
        }
    }
}